带有 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> {
见代码
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 classY<U>
, then the typeX<?>.Y<?>
is reifiable becauseX<?>
is reifiable andY<?>
is reifiable. The typeX<?>.Y<Object>
is not reifiable becauseY<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> {