泛型在使用instanceOf检查的内部类中表现得很奇怪

Moh*_*nan 3 java generics intellij-idea

看代码

public class AdnanTestClass<T> {

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

        }
    }

    private class TestInnerClass{

    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码在doForTest方法中给出了编译时错误.它说非法的仿制药类型.

如果我用这样的外类限定内部类

    if (o instanceof AdnanTestClass.TestInnerClass){

    }
Run Code Online (Sandbox Code Playgroud)

这个编译完全没问题.

if (o instanceof TestInnerClass)如果我<T>从我的班级声明中删除也会有效.

我不确定我在这里失踪了什么.是否存在符合外部资格的潜在问题.有人可以指出吗?我用intellij idea 14和Java 8做了这个测试.

Roh*_*ain 11

来自JLS§15.20.2:

如果在instanceof运算符之后提到的ReferenceType不表示可重新生成的引用类型(第4.7节),则为编译时错误.

现在,您的第一个代码:

if (o instanceof TestInnerClass)
Run Code Online (Sandbox Code Playgroud)

相当于:

if (o instanceof AdnanTestClass<T>.TestInnerClass)
Run Code Online (Sandbox Code Playgroud)

但是,由于AdnanTestClass<T>不可再生(参见JLS§4.7), AdnanTestClass<T>.TestInnerClass也不可再生,因此这不是一个有效的表达.该JLS部分的相关引用:

例如,如果泛型类X<T>具有泛型成员类 Y<U>,则该类型X<?>.Y<?>是可重新生成的,因为它X<?>是可重新生成的并且Y<?>是可恢复的.该类型X<?>.Y<Object>不可再生,因为Y<Object>不可再生.

相反,如果您将其更改为:

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

// or, raw type
if (o instanceof AdnanTestClass.TestInnerClass)
Run Code Online (Sandbox Code Playgroud)

这将是可以回收的,因此是有效的表达.