2012-06-23 93 views
1

在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>

+0

另請參見[*通用實例創建的類型推導*](http://docs.oracle.com/javase/7/docs/technotes/guides/language/type-in​​ference-generic-instance-creation.html) 。 – trashgod

回答

6

爲了表明該方法是一個泛型方法,使用/返回泛型類型。如果他們不存在,編譯器會尋找爲K具體類型,並命名爲V.

+0

這是實際詢問的問題的答案:) – Affe

1

因爲函數newInstance是通用的,以及,與一般類型ķ並且被轉發到HashMapV。它的意思是這樣使用:

HashMap<Integer, String> map = newInstance<Integer,String>(); 
1

要添加到其他的答案另一個具體類型,與擦除所有的類型都在編譯時丟失。但是,編譯器首先檢查驗證,這就是爲什麼需要類型。

這裏是從另一個SO answer擦除之後發生的事情爲例:

但使用仿製藥的時候,他們轉換成編譯時檢查和執行時間蒙上。所以這個代碼:

名單列表=新的ArrayList(); list.add(「Hi」); String x = list.get(0);

被編譯成

列表列表=新的ArrayList(); list.add(「Hi」); String x =(String)list.get(0);

1

能編譯合理地推斷類型參數?

是在本例的情況 - 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<>();}}可能是類型推斷爲以下之一:

  1. class X <K extends Object , V extends Object> { HashMap<K,V>newInstance(){return new HashMap<>();}}
  2. class X <K extends Object > { < V extends Object > HashMap<K,V>newInstance(){return new HashMap<>();}}
  3. class X <V extends Object> { < K extends Object > HashMap<K,V>newInstance(){return new HashMap<>();}}
  4. class X { <K extends Object , V extends Object> HashMap<K,V>newInstance(){return new HashMap<>();}}

此外,如果類型參數是推斷的又是什麼順序。當他們明確表示時,順序是顯而易見的。唯一的(對我來說)解決推斷類型參數的順序問題的方法是它們在代碼中聲明的順序。但是如果你只是顛倒了2行代碼的順序(這應該是無關緊要的),你可能會改變破壞構建的公共接口。非常脆弱!

相關問題