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
在所有Number
s 之间实现并且性能并不比强制转换为BigDecimal
.
添加回答
举报
0/150
提交
取消