2010-09-21 39 views
8
public static void main(String[] args) { 
    Map<String, Map<Long, List<String>>> map = getHashMap(); 
} 

static <K,V> Map<K,V> getHashMap() 
{ 
    return new HashMap<K, V>(); 
} 

我看到了谷歌番石榴類似的代碼(如工廠方法)作出的Hashmap的情況下,不提一般types.I不明白是怎麼一般是越來越受上述program.I推斷意味着怎能函數getHashMap瞭解映射的類型,因爲我沒有將任何類型信息傳遞給函數。如何在此處推斷泛型?

回答

6

getHashMap函數不必推斷類型。 Java語言規範要求javac推斷類型同意(15.12.2.7 Inferring Type Arguments Based on Actual Arguments)。我相信目前的計劃是(仍)爲JDK7來支持鑽石運營商,所以這種事情也可以與new一起工作,雖然有一些顯然毫無意義的語法。

Map<String, Map<Long, List<String>>> map = new HashMap<>(); 
                 ^^diamond 
+1

你能解釋一下嗎? – Emil 2010-09-21 12:55:28

+1

@Emil關於什麼? – 2010-09-21 12:56:07

+1

@Tom:你是什麼意思,javac會推斷出這個類型。你可以解釋這個東西是如何工作的。 – Emil 2010-09-21 12:59:16

1

在字節碼級的方法將有一個描述符只是說,有一個名爲getHashMap,不帶任何參數,並返回地圖(沒有仿製藥)的方法。

然後,當編譯器正在分析行Map<String, Map<Long, List<String>>> map = getHashMap();,它會說,好吧,我需要一個聲明類型爲Map<String, Map<Long, List<String>>>的變量,但實際上我需要調用一個方法。此時,編譯器的工作是檢查方法的返回類型是否與將結果分配給變量的聲明類型相匹配。因此,它會檢查String是否與K匹配,並且如果Map<Long, List<String>>與V匹配,則認爲賦值是類型安全的,並生成基本上使用Map(無泛型)變量的字節碼。

如果你會宣佈你的方法爲:

static <K extends Number,V> Map<K,V> getHashMap() 
{ 
    return new HashMap<K, V>(); 
} 

分析任務時,編譯器會看到String不匹配K extends Number,將拋出一個編譯錯誤,並不會創建字節碼那個任務。

1
class XX 
    static <T> T foo(){ return null; } 

String s = XX.foo(); 
Integer i = XX.foo(); 

Java推斷T在第一種情況下爲String,在第二種情況下爲Integer。

「推斷」是什麼意思?這意味着Java猜測在這兩個語句中,程序員最喜歡在第一種情況下需要T == String,對於第二種情況,T == Integer是一個好人,Java將這些猜測當做事實,程序員不需要要手動指定TS

String s = XX.<String> foo(); 
    Integer i = XX.<Integer>foo(); 

但實際上,Java的決定,返回類型T必須這樣來確定。

我覺得這個東西很腥,不知道背後的原因是什麼。也許,當(如果)的Java增加reifiable類型(即真正的類T可在運行時),設計更有意義:

class XX 
    static <T> T foo(){ return new T(); } 

String s = XX.foo(); 
Integer i = XX.foo(); 

我還是不喜歡的事實,方法的類型依賴於上下文。