带有 instanceOf 检查的 inner class 泛型行为很奇怪

generics behaves weird with inner class with instanceOf check

见代码

public class AdnanTestClass<T> {

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

        }
    }

    private class TestInnerClass{

    }
}

这段代码在doForTest方法中给出了编译时错误。它说非法泛型类型。

如果我像这样用外部 class 限定内部 class

    if (o instanceof AdnanTestClass.TestInnerClass){

    }

这编译得很好。

如果我从 class 声明中删除 <T>

if (o instanceof TestInnerClass) 也有效。

我不确定我在这里遗漏了什么。使用外部 class 排位是否存在潜在问题?有人可以指出吗?我用 intellij idea 14 和 Java 8 做了这个测试。

在你的例子中,o instanceof TestInnerClass 语法实际上是 o instanceof AdnanTestClass<T>.TestInnerClass 的 shorthand,但是由于类型参数(<T> 部分)在运行时被删除,所以简写是不再有效,因此 Java 编译器给你错误,并要求显式删除类型参数。

以下是关于泛型类型擦除的更多信息:http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

来自 JLS §15.20.2:

It is a compile-time error if the ReferenceType mentioned after the instanceof operator does not denote a reference type that is reifiable (§4.7).

现在,您的第一个代码:

if (o instanceof TestInnerClass)

相当于:

if (o instanceof AdnanTestClass<T>.TestInnerClass)

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

For example, if a generic class X<T> has a generic member class Y<U>, then the type X<?>.Y<?> is reifiable because X<?> is reifiable and Y<?> is reifiable. The type X<?>.Y<Object> is not reifiable because Y<Object> is not reifiable.

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

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

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

这将变得具体化,因此是有效的表达。

这个

if (o instanceof TestInnerClass){

等于

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

所以当没有明确说明外部 class 的 T 是什么时,您实际上无法检查 instanceof。 您的第二段代码忽略了 T,它是未定义的,但是对于内部 class,它已经明确

我认为你可以这样解决:

private class TestInnerClass<T> {