2009-09-01 14 views
5

我的問題與"Writing a generic class to handle built-in types"類似,包括受到處理矩陣操作的類的事實的啓發。 雖然這個問題被問及使用C#並且指向Generic Operators上的一篇文章。如何以通用的方式處理數字?

我不明白。 Java的號碼沒有一個add方法,所以你可以有這樣的方法:

public Number myAdd(Number a, Number b){ 
    return a.add(b); 
} 

那麼,你如何處理要能夠處理多種類型的數字在Java中的情況下?

回答

4

基本的問題是Java類型系統是非常原始的。由於在Java中沒有密封的一組類型的概念(Java也沒有可能推斷像Haskell那樣的類型),所以沒有辦法使一般數字+數字 - >數字沒有欺騙。

對於原語(以及可以自動映射到它們的Integer等類型的對象)類型的提升,+操作是語言的一部分。 (這是問題的實際部分:數字a +數字b應返回哪裏a和b是不同類型的?)

如果你真的想要這種行爲,你必須找到(或創建)你自己的自定義類,它使用反射或一系列(檢查和)轉換等。即使你使用泛型(記住泛型被類型化),鑄造也需要完成。

我想這些問題是爲什麼數字是平淡無奇的原因的一部分。

+0

「數字a +數字b返回哪裏a和b是不同類型的」幾乎是問題所在。 :) – 2009-09-01 08:21:38

-1

就個人而言,我幾乎所有的東西都使用BigDecimals(但主要是因爲我使用貨幣值)。他們處理任何大小的所有數值。因此,我認爲它們是一個通用的值,可以在您的假設示例中使用,而不是Number抽象類。 一切可以變成一個BigDecimal,爲什麼不使用它?

public BigDecimal myAdd(BigDecimal a, BigDecimal b) { 
    return a.add(b); 
} 

編輯:爲了解決以下BigBrothers評論,你總是可以使用的doubleValue()方法來創建自己的泛型方法。與此唯一的問題是,你可以在有人傳遞一個BigDecimal,少數情況下會失去精度,這是不是一個Double.maxValue

public Number myAdd(Number a, Number b) { 
    return new BigDecimal(a.doubleValue() + b.doubleValue()); 
} 

一個BigDecimal較大的是一個數字,所以返回一個是無後果。

+0

雖然我看到你在說什麼,但我希望能有更優雅的東西。 – 2009-09-01 01:56:47

3

我不明白。 Java的數量不 有一個add方法...

假設java.lang.Number也有add一種或多種方法,你會如何定義它的簽名?你如何定義它的語義?你將如何處理「混合模式」算法?

儘管回答這些問題和設計API無疑是可能的,但結果可能會很難正確使用。另外,應用程序需要執行「表示不可知」算法是最不尋常的。通常你需要/明確控制算術執行和轉換髮生的方式。 (Java的原始類型提升規則已經夠讓人難以避開他們的頭上!)

總而言之,我認爲太陽已經通過試圖支持算術了我們一個良好的服務號碼API。

3

你想得到的結果有多好?如果答案是「足夠好,大多是」,那麼這應該是必須的:

public Number myAdd(Number a, Number b){ 
    return a.doubleValue() + b.doubleValue(); 
} 

但是,如果你想要的東西,比方說,Java原始的推廣語義匹配,你很可能將不得不寫它自己。然後,您必須弄清楚「非標準」Number實現的所有組合的規則是什麼,包括BigDecimalBigInteger,AtomicDouble,AtomicLong,所有內容均爲org.apache.commons.lang.mutable,以及有人可能決定在下週二寫入的任何隨機實現。

目前尚不清楚在大多數情況下正確的做法是什麼 - 例如,將所有東西都轉換爲BigDecimal不是一種選擇,如果其中一個參數是Apache Commons的Fraction.ONE_THIRD;此外,以一般方式進行轉換與通常進行加法存在相同的問題。但方法Number將需要每個Number實現來處理所有這些情況 - 這可能是爲什麼它不在那裏。

0

由於其他指出的原因,您不能添加任何兩個數字,但可以添加相同類型的數字,結果也將是同一類型。 您可以用Java創建通用算術,像這樣的東西:

interface Arithmetics<T> { 
    T add(T val1, T val2); 
} 

class IntegerArithmetics implements Arithmetics<Integer> { 
    Integer add(Integer val1, Integer val2) { return val1 + val2; } 
} 

//similarly DoubleArithmetics, BigIntegerArithmetics, ... 

Generic Java Math庫正是這麼做的爲您服務。

1

一種實現泛型add方法的方法是讓左手參數推斷返回類型。

package mixins; 

import java.math.BigDecimal; 

public class Numbers { 

    public static boolean isZ(Number n) { 
     return n instanceof Integer || n instanceof Long || n instanceof Short || n instanceof Byte; 
    } 

    public static boolean isR(Number n) { 
     return n instanceof Double || n instanceof Float; 
    } 

    public static BigDecimal add(BigDecimal a, Number b) { 
     if (b instanceof BigDecimal) { 
      return a.add((BigDecimal) b); 
     } else if (isZ(b)) { 
      return a.add(new BigDecimal(b.longValue())); 
     } else if (isR(b)) { 
      return a.add(new BigDecimal(b.doubleValue())); 
     } 
     throw new IllegalArgumentException("No valid big decimal translation for " + b.getClass()); 
    } 

    public static Integer add(Integer a, Number b) { 
     return a + b.intValue(); 
    } 

    public static Long add(Long a, Number b) { 
     return a + b.longValue(); 
    } 

    public static Float add(Float a, Number b) { 
     return a + b.floatValue(); 
    } 

    public static Double add(Double a, Number b) { 
     return a + b.doubleValue(); 
    } 
} 

如果這是作爲靜態方法實現的,則可以使用靜態導入。

import static mixins.Numbers.*; 

public class Example { 

    public static void main(String[] args) { 
     BigDecimal fortytwo = new BigDecimal(42); 
     BigDecimal fiftyfive = add(fortytwo, 13); 
     System.out.println(fiftyfive); 
    } 

} 
相關問題