2015-03-19 48 views
3

見代碼泛型怪異的行爲與}這種內部類檢查

public class AdnanTestClass<T> { 

    public void doForTest(Object o){ 
     if (o instanceof TestInnerClass){ 

     } 
    } 

    private class TestInnerClass{ 

    } 
} 

這段代碼給出編譯時間錯誤在doForTest方法。它說非法的泛型類型。

,如果我有資格與外部類的內部類這樣

if (o instanceof AdnanTestClass.TestInnerClass){ 

    } 

這編譯完全正常。

if (o instanceof TestInnerClass)如果我從我的類聲明中刪除<T>也可以。

我不知道我在這裏錯過了什麼。是否有潛在的問題符合外部類。有人可以指出嗎?我做了這個測試用的IntelliJ IDEA 14與Java 8

回答

11

JLS §15.20.2

這是一個編譯時錯誤,如果 instanceof運算符後提到的引用類型並不表示一個引用類型,它是(§4.7)。

現在,你的第一個代碼:

if (o instanceof TestInnerClass) 

等同於:

if (o instanceof AdnanTestClass<T>.TestInnerClass) 

但是,因爲AdnanTestClass<T>不reifiable(見JLS §4.7), AdnanTestClass<T>.TestInnerClass也沒有reifiable,和因此這不是一個有效的表達。從JLS部相關報價:

例如,如果一個通用類X<T>有一個通用的構件類 Y<U>,那麼類型X<?>.Y<?>是reifiable因爲X<?>是 reifiable和Y<?>是reifiable。 X<?>.Y<Object>類型不是 ,因爲Y<Object>不可確定。

相反,如果把它修改成:

// unbounded wildcard 
if (o instanceof AdnanTestClass<?>.TestInnerClass) 

// or, raw type 
if (o instanceof AdnanTestClass.TestInnerClass) 

將成爲reifiable,因此是有效的表達。

+0

夢幻** Refiable說明** ! – 2015-03-19 11:21:18

3

在你的情況o instanceof TestInnerClass語法實際上是o instanceof AdnanTestClass<T>.TestInnerClass但由於類型參數(<T>部分)在運行時被擦除的簡寫,即短手不再有效,因此Java編譯器爲您提供了錯誤,並要求顯式刪除類型參數。

這裏有一個關於泛型類型擦除的更多信息:http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

2

if (o instanceof TestInnerClass){ 

等於

if (o instanceof AdnanTestClass<T>.TestInnerClass){ 

,所以你不能actully檢查instanceof當它沒有明確說什麼外部類的T是。 你的代碼的第二塊忽略T,這是不確定的,但那麼,對於一個內部類,它是已經明確的

我認爲你可以解決它像這樣:

private class TestInnerClass<T> { 
+1

@NeerajJain umm ....不 – 2015-03-19 11:14:33