[英]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.