2010-10-06 41 views
29

我想創建一個Java中的泛型類,它將對數字執行操作。在下面的例子,此外,如下:我可以在Number基類上進行算術運算嗎?

public class Example <T extends Number> { 

    public T add(T a, T b){ 
     return a + b; 
    } 

} 

請原諒我的幼稚,因爲我是比較新的Java的泛型。此代碼無法編譯與錯誤:

The operator + is undefined for the argument type(s) T, T

我認爲,增加「擴展數字」代碼將編譯。是否有可能做這個Java或我將不得不爲每個數字類型創建重寫的方法?

+1

如果你想要做這種事情,可能希望查看Scala或Groovy。他們有運算符重載和域特定的語言功能:) – 2010-10-09 18:54:10

回答

26

號碼沒有與其關聯的+運算符,也不可以,因爲沒有運算符重載。

這將是很好,雖然。

基本上,你要求java自動載入Number的一個加號,後者恰好包含Integer,Float和Double,可以自動加載並應用一個加號運算符,但是,可能有任何數量的其他未知的Number後裔不能被自動裝箱,並且直到運行時才能知道。 (該死的擦除)

+3

「可能有任何數量的其他未知的數字後代不能自動複製,」如BigInteger和BigDecimal都擴展了Number。 – Powerlord 2010-10-06 14:53:37

+0

我想,如果Number有.add(a,b).sub(a,b).mult(a,b)...我們可以簡單地使用它們,所以使用泛型,可能是由NumberHero實現的接口IntegerHero可以擴展一個類似Integer的類(因爲我們不能擴展最終類),可以做到這一點嗎? – 2015-12-22 19:05:27

0

考慮Example<Number>+將如何工作?沒有addNumber或類似的Integer

更糟的是考慮final class FunkyNumber extends Number { ... weird stuff, no add op ... }

1

也有類似的問題,這個答案是你不能這樣做。

您可以檢查a和b是長/雙/整數/等的實例。並委派附加到類似的方法:

public Integer add(Integer a, Integer b) { 
    return a+b; // this actually uses auto boxing and unboxing to int 
} 

而且你需要創建一個爲每個擴展號碼類型,所以這不是真的可行。換句話說,不要使用泛型進行數字操作。作爲超類的數量相當有限。

17

你的問題並沒有真正涉及到泛型,而是涉及到操作符,基元對象和自動裝箱。

想想這個:

public static void main(String[] args) { 
    Number a = new Integer(2); 
    Number b = new Integer(3); 
    Number c = a + b; 
} 

上面沒有編譯

public static void main(String[] args) { 
    Integer a = new Integer(2); 
    Integer b = new Integer(3); 
    Number c = a + b; 
} 

以上確實編譯,但僅僅是因爲自動裝箱的 - 這是一種在推出哈克語法膠水Java 5,並且只能在編譯時使用一些具體的類型:int-Integer。

在幕後,Java編譯器被改寫最後一條語句(「我一定要拆箱ab與原始數據類型應用和運營商,以及框中的結果將它指定對象c」)這樣的:

Number c = Integer.valueOf(a.intValue() + b.intValue()); 

Java無法取消裝箱Number,因爲它不知道在編譯時的具體類型,因此它不能猜測它的原始對應物。

2

是的,Nathan是對的。如果你想這樣的事情,你必須把它寫自己

public class Example <T extends Number> { 
    private final Calculator<T> calc; 
    public Example(Calculator<T> calc) { 
     this.calc = calc; 
    } 

    public T add(T a, T b){ 
     return calc.add(a,b); 
    } 
} 

public interface Calculator<T extends Number> { 
    public T add(T a, T b); 
} 

public class IntCalc implements Calculator<Integer> { 
    public final static IntCalc INSTANCE = new IntCalc(); 
    private IntCalc(){} 
    public Integer add(Integer a, Integer b) { return a + b; } 
} 

... 

Example<Integer> ex = new Example<Integer>(IntCalc.INSTANCE); 
System.out.println(ex.add(12,13)); 

太糟糕了Java沒有類型類(哈斯克爾)或隱式對象(斯卡拉),這個任務將是一個完美的使用情況...

3

你可以做這樣的事情

class Example <T extends Number> { 
     public Number add(T a, T b){ 
      return new Double(a.doubleValue() + b.doubleValue()); 
     } 
    } 
0

即使Java運行時庫有這個問題,大多數的處理原語的方法有重複相同的功能。

最快的選擇是爲一種類型編寫代碼,然後複製它並替換類型以生成其他類型的方法。一個簡短的腳本應該足以做到這一點。