[英]Java Generics won't compile
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
无法理解我在做什么错? 如果我使用Integer更改SZX-一切正常,但为什么不能使用泛型代码编译?
重构代码为:
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
,怎么可能呢? 为什么没有自动装箱?
您遇到的问题是,因为没有+
的定义运营商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;
}
这称为类型擦除 。
如果未为Number
定义+
,则不允许使用此代码。
对于所有内置的通用解决方案Number
扩展:
public static Number sum(final Number a, final Number b) {
return new BigDecimal(a.toString()).add(new BigDecimal(b.toString()));
}
(注意:不能保证toString()
会给出一个可由BigDecimal
解析的String
,但据我所知,它对所有内置的JDK Number
扩展都是如此。)
如果您想做一些更聪明的事情,可以对instanceof
进行一些检查,以找到输入的类型并从那里开始工作,但是我尝试过一次,以便在所有Number
之间实现Comparable
,而性能也没有比强制转换更好到BigDecimal
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.