2010-10-13 162 views
10

我想創建一個方法來比較一個數字,但可以有一個輸入是任何數字的子類。Java泛型和數字類

我已經看過以下方式做這個...

public static <T extends Number> void evaluate(T inputNumber) { 
    if (inputNumber >= x) { 
    ... 
    } 
} 

我需要得到實際的靈長類動物之前,我可以進行比較,數類有方法來檢索每個靈長類動物,但我想要一個乾淨的方式來選擇正確的方法。

這可能嗎?

乾杯

+0

相關:【JAVA:泛型方法和數字] (http://stackoverflow.com/questions/3850970/java-generic-methods-and-numbers)。 – BalusC 2010-10-13 11:44:32

回答

4

不幸的是,沒有辦法使用if/else塊從包裝類型中獲取原始類型。

問題是,它不可能以通用的方式實現這樣的方法。這裏有一些看起來可能的方法,可以期望在數字類中找到:

public abstract X getPrimitiveValue(); 

這將是很好的,不是嗎?但是這是不可能的。有沒有可能的X上可以超過int抽象,floatdouble

public abstract Class<?> getCorrespondingPrimitiveClass(); 

這沒有幫助的,因爲沒有辦法實例的原始類。

因此,您可以做的唯一一件事對所有類型都是通用的,即使用longValue()doubleValue()方法,但是如果您處理的是錯誤類型,則會丟失信息。

因此否:java編號層次結構不適合以通用的方式解決這些問題。

0

在這種情況下,你可以用普通的方法,不使用泛型

+0

所以,如果方法是接受一個double或一個整數,那麼我需要兩個不同簽名的方法,或者我錯過了什麼? – 2010-10-13 11:32:58

+0

@Mr_R:如果您使用Java 5,則自動裝箱會將其轉換爲Double和Integer,這兩者都實現Number。 – 2010-10-13 11:40:46

+2

利用多態性,只需提供一個「評估(數量)」方法 – 2010-10-13 11:45:50

8

Number API不提供一個乾淨的方式來獲得的價值;您必須使用instanceof

一種解決方案是將這些值「摺疊」爲兩種類型:longdouble。這樣,您可以使用此代碼:

if(inputNumber instanceof Float || inputNumber instanceof Double) { 
    double val = inputNumber.doubleValue(); 
    ... 
} else { 
    long val = inputNumber.longValue(); 
    ... 
} 

請注意,這僅適用於本標準編號類型,但Number也受到了很多其他類型的(AtomicIntegerBigDecimal)的實現。

如果你想支持所有類型的,一招就是用BigDecimal

BigDecimal value = new BigDecimal(inputNumber.toString()); 

,應始終工作,併爲您提供最精確的結果。

2

<T extends Number>方法總是麻煩,因爲你不能真正做任何事情的數字(所有的操作符都爲兒童定義)。您需要爲Number的每個孩子做一大堆instanceof,並通過轉換爲子類型來處理該情況。或者(我認爲更好 - 這就是Sun做這件事的方式)就是爲每個孩子類型設置一個方法,可能利用拳擊/取消裝箱操作,如+, - ,>等,這是可能的(所有的包裝,不是對於BigInteger/BigDecimal或任何自定義類型)。

1

如果它真的只是參數比較同類型參數的另一個值那麼你可以做以下的(只是在T x爲了簡單相加)

public static <T extends Number & Comparable<? super Number>> int evaluate(T inputNumber, T x) { 
      if (inputNumber.compareTo(x) > 0) { ... } 
    }