2013-05-28 72 views
1
public class ExplicitTypeSpecification { 

    static void f(Map<Integer, String> map){} 

    public static void main(String[] args){ 
     New c = new New(); 
     f(c.map()); 
    } 
} 

class New <K, V>{ 
    Map<K, V> map(){ 
     return new HashMap<K, V>(); 
    } 
} 

此代碼編譯時沒有錯誤。參數化類vs參數化方法

然後,我們在做新類的某些變化:

class New { 
    <K, V>Map<K, V> map(){ 
     return new HashMap<K, V>(); 
    } 
} 

我們只是參數的方法map(),而不是整個類。但是,在這種情況下,編譯錯誤的行f(c.map()); occures

java: f(java.util.Map<java.lang.Integer,java.lang.String>) in 
Generics.ExplicitTypeSpecification.ExplicitTypeSpecification cannot be applied to 
(java.util.Map<java.lang.Object,java.lang.Object>)* 

我們可以指向明確的類型f(c.<Integer, String>map());但我感興趣的是爲什麼我們得到一個編譯錯誤?

在這兩種情況下,方法map()都會返回Map<Object, Object>對象,但在第一種情況下,我們只會收到未檢查分配的警告。

問題:爲什麼在第二種情況下我們有更嚴格的類型檢查?

什麼是new HashMap()HashMap<Object, Object>()之間的dirrefence?回答這個問題解決了它。

+0

有趣的發現,特別是因爲'Map map = c.map(); f(地圖);'編譯。我認爲這與編譯器猜測「K」和「V」的正確值的能力有關。 – Cephalopod

回答

2

在第一種情況下,您使用的是原始類型New(而不是New<Integer, String>),因此所有通用類型檢查都被禁用。這適用於舊(Java 1.4)代碼的兼容模式。

+0

但在第二種情況下,我也使用原始類型'New'。我剛剛更改了類和方法參數化。我的問題是爲什麼在這種情況下啓用了泛型類型檢查? – AJlxuMuk

+0

在第二種情況下,'New'不是通用的,所以它只是一種類型,沒有原始類型等,因此編譯器不會禁用通用類型檢查。相反,它試圖自動推斷'c.map()'返回類型的泛型類型並失敗。使用'Map map = c.map();'來查看自動推理的工作。 –

0

如果您未指定類型參數,則向後兼容Java 1.4會假設您需要「對象」。另外,你會得到一個關於這個的警告。

所以你的功能等同於:

public static void main(String[] args){ 
    New c = new New(); 
    f(c.<Object, Object>map()); 
} 

然後你得到一個錯誤,說你要使用其中一個參數Map<Integer, String>預期值Map<Object, Object>

注意:Map<Integer, String>不是Map<Object, Object>的子類型。

+0

你說得對。 **但**如果您使用**參數化類**(不是參數化方法) - 頂部的代碼,您**不會收到錯誤**。注意,在這種情況下,方法map()還返回'Map ',因爲New對象是raw,當它真的需要'Map '時,方法f()獲取這個對象作爲參數。 – AJlxuMuk