我有一個關於在編碼中使用「最佳實踐」的基本問題。 (我使用的是Java,但是問題對於OOP是通用的。)爲長期使用的類編寫方法時,是否最好使用或不使用泛型的返回對象?應該返回語句在Java中使用泛型?
具體在我的情況下,我將返回一個Map<String, Integer>
與該方法。我是否應該在退貨聲明中說明這一點,或者我應該簡單地返回Map
?
我有一個關於在編碼中使用「最佳實踐」的基本問題。 (我使用的是Java,但是問題對於OOP是通用的。)爲長期使用的類編寫方法時,是否最好使用或不使用泛型的返回對象?應該返回語句在Java中使用泛型?
具體在我的情況下,我將返回一個Map<String, Integer>
與該方法。我是否應該在退貨聲明中說明這一點,或者我應該簡單地返回Map
?
只要有可能,最好使用泛型。它將有助於避免運行時異常,並且不會強制使用您的代碼的人執行一堆醜陋的類型轉換。例如,如果您使用以下簽名:
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時會得到一個異常。
你一定要返回地圖<字符串,而不是是否有意義在你的方法,因爲這將使它更容易爲他人使用該方法一個普通的地圖整數> - 獲取地圖<字符串後,整數>他們將能夠檢索字符串鍵和整數值,而不必每次都從通用對象中轉換它們(這也使得它更具類型安全性,因爲這樣他們就會知道鍵和值是什麼,即使沒有閱讀javadoc方法)。
所以總之,肯定會返回泛型。
如果要返回集合,則應該包含該集合包含的通用類型。例如:
public Map<String, Blammo> getBlammoMap(...)
是(IMHO)優選
public Map getBlammoMap(...)
因爲它
kapowMap = (Map<String, Kapow> getBlammoMap()
)的選項。我認爲越具體越好。如果你的方法返回一個總是以Strings爲關鍵字的地圖,並且Integers爲值,那麼絕對使用Map有返回類型。這樣,任何調用代碼都知道他們正在得到什麼。如果返回類型只是Map,那麼調用代碼將不知道鍵和值的類是什麼(除Object以外)。
一般來說,您應該總是指定參數化地圖,列表等,以便知道它包含的內容。這對迭代它們非常有用,你可以使用java foreach。
for (String currKey : myMap.keySet())
{
System.out.println("curr Key: " + currKey + " curr Value: " + myMap.get(currKey));
}
這消除了任何額外的迭代器或鑄造。
何浩豪!一個美好的新年問題。
您一般必須(必須)返回適當的通用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));
}
}
的問題是,它是否
試着猜。然後編譯(是的,它編譯),看看會發生什麼。
現在確實不適用於你的情況。但有一個習慣總是指定類型,即使它只是Map<?,?>
,是非常有益的。你不會輸。
一般情況下,你的類型的參數,輸入和輸出,應該捕捉精確的功能特異性的水平。在函數式編程中,他們甚至說「類型就是文檔」。如果我看到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
(或由u
的U
)生成的String
。「
的嗜好性,顯然要儘可能對未來的程序員一樣清楚(自己或他人)。正如返回Map
沒有類型params爲晦澀難懂,所以也將返回Map<String, Integer>
可能是過度限制(從而誤導),如果你的foo
會工作同樣好,比方說,Map<String, Long>
我不明白你在問什麼,你可以包括你的問題的兩個備選方案的代碼? – 2012-01-05 21:22:42
返回一個「通用增強型」地圖對於代碼清晰性和類型安全性來說總是最好的,即使在運行時忘記了泛型類型信息。它使API用戶更加清楚 – fge 2012-01-05 21:23:55
這個問題對於OOP來說並不普遍,除非你暗示泛型是面向對象開發的標準功能。 – Perception 2012-01-05 22:34:49