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

时间:2015-03-19 11:01:05

标签: java generics intellij-idea

参见代码

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做了这个测试。

3 个答案:

答案 0 :(得分:11)

来自JLS §15.20.2

  

如果在之后提到的ReferenceType是一个编译时错误   instanceof运算符不表示可重新生成的引用类型   (§4.7)。

现在,您的第一个代码:

if (o instanceof TestInnerClass)

相当于:

if (o instanceof AdnanTestClass<T>.TestInnerClass)

但是,由于AdnanTestClass<T>无法恢复(请参阅JLS §4.7), AdnanTestClass<T>.TestInnerClass也不可恢复,因此这不是一个有效的表达式。该JLS部分的相关引用:

  

例如,如果泛型类X<T>具有泛型成员类   Y<U>,然后类型X<?>.Y<?>可以恢复,因为X<?>是。{1}}   可以恢复,Y<?>可以恢复。类型X<?>.Y<Object>不是   可以回复,因为Y<Object>不可再生。

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

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

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

这将成为可以恢复的,因此是有效的表达。

答案 1 :(得分:3)

在您的情况下,o instanceof TestInnerClass语法实际上是o instanceof AdnanTestClass<T>.TestInnerClass的简写,但由于类型参数(<T>部分)在运行时被删除,因此该短手不再有效,因此Java编译器为您提供错误,并要求显式删除类型参数。

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

答案 2 :(得分:2)

if (o instanceof TestInnerClass){

等于

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

因此,如果instanceof没有明确说明外部课程T是什么,则无法正确检查T。 你的第二段代码忽略private class TestInnerClass<T> { ,它是未定义的,但是对于内部类,它已经是明确的

我认为你可以这样解决:

{{1}}