2011-12-20 145 views
9

我剛碰到一些我不明白的東西。爲什麼不是每個循環低於合法時,當第二個相同的是?Java泛型和返回類型

public interface SomeInterface<T> { 
    List<SomeNamedObject> getObjects(); 
    void doSomething(P1 p1, T p2); 
} 

public class SomeNamedObject { 
    private String text; 
} 

public class Clazz { 

    private SomeInterface someInterface; 

    ... 

    public void someMethod() { 
     // Error Type mismatch: cannot convert from element type Object to TestClass.SomeNamedObject 
     for (SomeNamedObject someNamedObject : someInterface.getObjects()) { 
      // This loop won't compile as the someInterface.getObjects returns just a List and not a List<SomeNamedObject> 
     } 

     // Warning Type safety: The expression of type List needs unchecked 
     // conversion to conform to List<TestClass.SomeNamedObject> 
     List<SomeNamedObject> objects = someInterface.getObjects(); 
     for (SomeNamedObject someNamedObject : objects) { 
      // This loop compiles 
     } 
    } 
} 
+0

不是一個錯誤,它是一個擦除和原始類型的問題。 – Stefan 2011-12-20 18:26:25

+0

我沒有看到問題可能是什麼。你可以發佈實際的堆棧跟蹤(只是前幾行)。我猜你的全班學生需要「SomeInterface 」,但這個例子並不需要「」也許裏面有東西嗎? – Jay 2011-12-20 18:27:07

+1

@Jay他的someInterface的聲明沒有指定泛型類型,然後Java退回到原始類型,並且方法簽名更改爲返回原始列表(請參閱答案)。他應該提到關於對象分配的警告。 – Stefan 2011-12-20 18:34:47

回答

18

因爲你的實例變量private SomeInterface someInterface沒有指定其泛型類型參數,那麼所有使用泛型是someInterface禁用。這意味着someInterface.getObjects()具有原始返回類型List而不是List<SomeNamedObject>。這是第一個例子不能編譯的原因。

在第二個示例中List<SomeNamedObject> objects = someInterface.getObjects()正在爲列表顯示一個明確的類型。當你這樣做時,你會看到一個警告,但因爲不能保證類型安全。如果getObjects()被定義爲只有List getObjects()而沒有類型參數,這與您會看到相同的行爲。

+0

它可能是原文中的一個錯字,但'SomeInterface '不使用'T'來指定被返回的'List'的通用類型,它被硬編碼爲'SomeNamedObject'。所以,即使實例變量沒有輸入,它也不應該影響返回的List。 – 2011-12-20 18:29:20

+5

如果通用參數未在'someInterface'聲明中指定,那麼即使'SomeInterface'中的* all *泛型類型不依賴於'T',也會被忽略/禁用。 – mikej 2011-12-20 18:32:13

+0

非常有趣,雖然奇特。 – 2011-12-20 18:34:04

3

您應該注意,當您在第二個循環之前對對象賦值時會得到編譯器警告。

Type safety: The expression of type List needs unchecked conversion to conform to 
List<TestClass.SomeNamedObject> 

這會告訴你,由於某種原因,你的getObjects()方法返回一個非泛化的List。這解釋了爲什麼第一個循環不能編譯。

因爲你忘了泛型化您參考:如果你不泛型化這一切都將使用原始類型,包括申報方法的簽名

private SomeInterface someInterface; 

。意味着它返回一個列表生對象,而不是一個列表<SomeNamedObject> 的像做

private SomeInterface<Object> someInterface; 

,它應該工作。