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。例如,+是为 等定义的Integer,Double但不是BigInteger,BigDecimal或 的任何其他非标准实现Number。
没有很好的方法来进行泛型加法。您最终不得不提供一个BinaryOperator<S>,因此您的代码如下所示:
sum(1, 2, Integer::sum); sum(1.0, 2.0, Double::sum);
这比仅仅更冗长:
1 + 2 1.0 + 2.0
需要+为 和 的编译时类型定义编译v1器v2。它们是否在运行时(或其他什么)并不重要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,则不允许使用此代码。
慕神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.
添加回答
举报
0/150
提交
取消
