簡體   English   中英

Java泛型無法編譯

[英]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 Integerint cannot be converted to S ,怎么可能呢? 為什么沒有自動裝箱?

您遇到的問題是,因為沒有+的定義運營商Number ,只對特定的子類Number 例如, +是為IntegerDouble等定義的,但不是BigIntegerBigDecimalNumber任何其他非標准實現的。

沒有通用的加法的好方法。 您最終不得不提供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;
 }

這稱為類型擦除

如果未為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM