在Java中的這個靜態函數中,爲什麼在第1行中必須重複<K, V>
?爲什麼類型參數必須重複兩次?
public static <K, V> HashMap<K, V> newInstance() {
return new HashMap<K, V>();
}
我明白爲什麼HashMap<K, V>
是必要的,因爲該函數返回分別與泛型類型K和V一個HashMap的鍵和值。但是,函數簽名中爲什麼需要第一個<K, V>
?
在Java中的這個靜態函數中,爲什麼在第1行中必須重複<K, V>
?爲什麼類型參數必須重複兩次?
public static <K, V> HashMap<K, V> newInstance() {
return new HashMap<K, V>();
}
我明白爲什麼HashMap<K, V>
是必要的,因爲該函數返回分別與泛型類型K和V一個HashMap的鍵和值。但是,函數簽名中爲什麼需要第一個<K, V>
?
因爲函數newInstance
是通用的,以及,與一般類型ķ並且被轉發到HashMap
V。它的意思是這樣使用:
HashMap<Integer, String> map = newInstance<Integer,String>();
要添加到其他的答案另一個具體類型,與擦除所有的類型都在編譯時丟失。但是,編譯器首先檢查驗證,這就是爲什麼需要類型。
這裏是從另一個SO answer擦除之後發生的事情爲例:
但使用仿製藥的時候,他們轉換成編譯時檢查和執行時間蒙上。所以這個代碼:
名單列表=新的ArrayList(); list.add(「Hi」); String x = list.get(0);
被編譯成
列表列表=新的ArrayList(); list.add(「Hi」); String x =(String)list.get(0);
能編譯合理地推斷類型參數?
是在本例的情況 - static HashMap<K,V>newInstance(){return new HashMap<>();}
顯然簡稱static < K extends Object , V extends Object > HashMap<K,V>newInstance()return new HashMap<K,V>();}
。
但是,如果你的編譯器推斷類型的參數,那麼你的代碼仍然會當你敲錯類名編譯均勻。 static void setName (Sting name)
可能是錯誤的,但您的編譯器會假設您的意思是<Sting extends Object> static void setName (Sting name);
通過運行時擦除的魔術將相當於static void setName (Object name) ;
。
如果該方法不是靜態的,那麼推論成爲問題。 class X { HashMap<K,V>newInstance(){return new HashMap<>();}}
可能是類型推斷爲以下之一:
class X <K extends Object , V extends Object> { HashMap<K,V>newInstance(){return new HashMap<>();}}
class X <K extends Object > { < V extends Object > HashMap<K,V>newInstance(){return new HashMap<>();}}
class X <V extends Object> { < K extends Object > HashMap<K,V>newInstance(){return new HashMap<>();}}
class X { <K extends Object , V extends Object> HashMap<K,V>newInstance(){return new HashMap<>();}}
此外,如果類型參數是推斷的又是什麼順序。當他們明確表示時,順序是顯而易見的。唯一的(對我來說)解決推斷類型參數的順序問題的方法是它們在代碼中聲明的順序。但是如果你只是顛倒了2行代碼的順序(這應該是無關緊要的),你可能會改變破壞構建的公共接口。非常脆弱!
另請參見[*通用實例創建的類型推導*](http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-inference-generic-instance-creation.html) 。 – trashgod