2012-01-05 43 views
3

我有一個關於在編碼中使用「最佳實踐」的基本問題。 (我使用的是Java,但是問題對於OOP是通用的。)爲長期使用的類編寫方法時,是否最好使用或不使用泛型的返回對象?應該返回語句在Java中使用泛型?

具體在我的情況下,我將返回一個Map<String, Integer>與該方法。我是否應該在退貨聲明中說明這一點,或者我應該簡單地返回Map

+3

我不明白你在問什麼,你可以包括你的問題的兩個備選方案的代碼? – 2012-01-05 21:22:42

+2

返回一個「通用增強型」地圖對於代碼清晰性和類型安全性來說總是最好的,即使在運行時忘記了泛型類型信息。它使API用戶更加清楚 – fge 2012-01-05 21:23:55

+1

這個問題對於OOP來說並不普遍,除非你暗示泛型是面向對象開發的標準功能。 – Perception 2012-01-05 22:34:49

回答

9

只要有可能,最好使用泛型。它將有助於避免運行時異常,並且不會強制使用您的代碼的人執行一堆醜陋的類型轉換。例如,如果您使用以下簽名:

Map<String, Integer> getMap(); 

...那麼消費代碼可能是這樣的:

Map<String, Integer> map = getMap(); 
Integer val = map.get(key); 

...但如果你使用的簽名是這樣的:

Map getMap(); 

...消費代碼可能是這樣的:

Map<String, Integer> map = (Map<String, Integer)getMap(); 
Integer val = map.get(key); 

通過使用泛型,您不僅可以保存(Map<String, Integer>)強制轉換,但是如果您更改getMap以實際返回Map<String, Object>,您將收到編譯時錯誤(這很容易被捕獲和修復),而不是可能的當你打電話給map.get(key)並且JRE試圖將一些隨機對象自動轉換爲一個Integer時會得到一個異常。

3

你一定要返回地圖<字符串,而不是是否有意義在你的方法,因爲這將使它更容易爲他人使用該方法一個普通的地圖整數> - 獲取地圖<字符串後,整數>他們將能夠檢索字符串鍵和整數值,而不必每次都從通用對象中轉換它們(這也使得它更具類型安全性,因爲這樣他們就會知道鍵和值是什麼,即使沒有閱讀javadoc方法)。

所以總之,肯定會返回泛型。

3

如果方法明確打算使用某種類型(即只有String),那麼可以返回List<String>。如果方法是通用類型參數T,則可以返回List<T>

我不會簡單地返回Map,因爲通常會導致混淆和更多的鍋爐代碼轉換爲所需的類型。

+0

有沒有'地圖'或'地圖'-'Map'有_two_類型參數。 – alf 2012-01-05 21:42:56

+0

@alf:是的,對不起,當我輸入那個時,我正在考慮列表或其他內容。 :) – Tudor 2012-01-05 21:53:21

3

如果要返回集合,則應該包含該集合包含的通用類型。例如:

public Map<String, Blammo> getBlammoMap(...) 

是(IMHO)優選

public Map getBlammoMap(...) 

因爲它

  1. 限制壞鑄造(即kapowMap = (Map<String, Kapow> getBlammoMap())的選項。
  2. 告訴消費者該方法實際返回的內容。
1

我認爲越具體越好。如果你的方法返回一個總是以Strings爲關鍵字的地圖,並且Integers爲值,那麼絕對使用Map有返回類型。這樣,任何調用代碼都知道他們正在得到什麼。如果返回類型只是Map,那麼調用代碼將不知道鍵和值的類是什麼(除Object以外)。

一般來說,您應該總是指定參數化地圖,列表等,以便知道它包含的內容。這對迭代它們非常有用,你可以使用java foreach。

for (String currKey : myMap.keySet()) 
{ 
    System.out.println("curr Key: " + currKey + " curr Value: " + myMap.get(currKey)); 
} 

這消除了任何額外的迭代器或鑄造。

1

何浩豪!一個美好的新年問題。

您一般必須(必須)返回適當的通用Map<Whatever, YouNeed>。這聽起來很瘋狂,但只要你使用任何沒有類型參數的泛型類型,你就會陷入困境。

問題將如下所示:在代碼中使用的原始類型,改變了方法(甚至看似不相關的方法)的解決方式。查找由Joshua Bloch和Bill Pugh撰寫的演示文稿,名爲「Java Puzzlers:刮爛桶的底部」,瞭解詳細信息,我正在準備示例:)該視頻的詳細信息是http://www.parleys.com/#id=2168&st=5(您可能希望滾動到幻燈片44, 5. 「Glommer樁」)

所以這裏有一個例子:

/** 
* (c) (as far as I know) Joshua Bloch and Bill Pugh, 2010 
*/ 
public class Glommer<T> { 
    String glom(Collection<?> objs) { 
     String result = ""; 
     for (Object o : objs) result += o; 
     return result; 
    } 

    int glom(List<Integer> ints) { 
     int result = 0; 
     for (int i : ints) result += i; 
     return result; 
    } 

    public static void main(String args[]) { 
     List<String> strings = Arrays.asList("1", "2", "3"); 
     System.out.println(new Glommer().glom(strings)); 
    } 
} 

的問題是,它是否

  • 打印6
  • 打印123
  • 拋出異常,
  • 或執行其他操作。

試着猜。然後編譯(是的,它編譯),看看會發生什麼。

現在確實適用於你的情況。但有一個習慣總是指定類型,即使它只是Map<?,?>,是非常有益的。你不會輸。

The obligatory Java Generics FAQ link

2

一般情況下,你的類型的參數,輸入和輸出,應該捕捉精確的功能特異性的水平。在函數式編程中,他們甚至說「類型就是文檔」。如果我看到Map foo(Arg args)我認爲foo絕不關心在它返回的地圖類型,但不知何故,依靠參數數量的東西。「如果我看到Map<T,String> foo(T t, Arg arg)Map<T, U> foo(T t, U u)我會想」 OK,FOO產生基於其t的類型的映射和由Arg(或由uU)生成的String。「

的嗜好性,顯然要儘可能對未來的程序員一樣清楚(自己或他人)。正如返回Map沒有類型params爲晦澀難懂,所以也將返回Map<String, Integer>可能是過度限制(從而誤導),如果你的foo會工作同樣好,比方說,Map<String, Long>