为了账号安全,请及时绑定邮箱和手机立即绑定

Java 泛型无法编译

Java 泛型无法编译

慕哥6287543 2022-12-28 14:21:01
public class GenMethodDemo{        public GenMethodDemo(){            Sum.<Integer,Integer,Integer>sum(1,2);               }        public static void main(String args[]){            new GenMethodDemo();        }    }    class Sum{     public static final <S extends Number,Z extends S,X extends S> S sum(Z v1,X v2){            System.out.printf("v1=%1$s,v2=%2$s%n",v1.getClass(),v2.getClass());            return v1+v2;        }错误得到:error: bad operand types for binary operator '+'        return v1+v2;  first type:  Z  second type: X  where Z,S,X are type-variables:    Z extends S declared in method <S,Z,X>sum(Z,X)    S extends Number declared in method <S,Z,X>sum(Z,X)    X extends S declared in method <S,Z,X>sum(Z,X)1 error不明白我做错了什么?如果我将 SZX 更改为 Integer - 一切正常,但为什么使用泛型代码无法编译?重构代码为:public class GenMethodDemo2{    public GenMethodDemo2(){        Sum.<Integer>sum(1,2);            }    public static void main(String args[]){        new GenMethodDemo2();    }}class Sum{    public static final <S extends Integer> S sum(S v1,S v2){        System.out.printf("v1=%1$s, v2=%2$s%n",v1.getClass(),v2.getClass());        return v1+v2;    }} error: incompatible types: int cannot be converted to S        return v1+v2;  where S is a type-variable:    S extends Integer declared in method <S>sum(S,S)1 error因此,S 应该是 Integer 或 Integer 类的任何子类,以任何方式绝对应该可以 + 它们的值。这个版本有什么问题?S extends Integer但是int cannot be converted to S,怎么可能呢?为什么没有自动装箱?
查看完整描述

2 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

您遇到的问题是因为没有为+定义运算符Number,只有 的特定子类Number。例如,+是为 等定义的IntegerDouble但不是BigIntegerBigDecimal或 的任何其他非标准实现Number

没有很好的方法来进行泛型加法。您最终不得不提供一个BinaryOperator<S>,因此您的代码如下所示:

sum(1, 2, Integer::sum);
sum(1.0, 2.0, Double::sum);

这比仅仅更冗长:

1 + 2
1.0 + 2.0

需要+为 和 的编译时类型定义编译v1v2。它们是否在运行时(或其他什么)并不重要Integer:是否允许+由编译器决定,因为它必须能够保证该方法对于任何参数都是类型安全的。

上面的方法编译成这样:

 public static final Number sum(Number v1, Number v2){
   System.out.printf("v1=%1$s,v2=%2$s%n",v1.getClass(),v2.getClass());
      return v1+v2;
 }

这称为类型擦除

如果+没有为 a 定义Number,则不允许使用此代码。


查看完整回答
反对 回复 2022-12-28
?
慕神8447489

TA贡献1780条经验 获得超1个赞

作为所有内置Number扩展的通用解决方案:

public static Number sum(final Number a, final Number b) { 
   return new BigDecimal(a.toString()).add(new BigDecimal(b.toString()));
}

(注意:不能保证toString()会给出String可解析的,BigDecimal但据我所知,它适用于所有内置的 JDKNumber扩展。)

如果你想做一些更聪明的事情,你可以做一些检查instanceof以找到输入的类型并从那里开始工作,但我试过一次Comparable在所有Numbers 之间实现并且性能并不比强制转换为BigDecimal.


查看完整回答
反对 回复 2022-12-28
  • 2 回答
  • 0 关注
  • 129 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号