假设:
public class C<T> {
private class D {
public boolean equals( Object o ) {
if ( !(o instanceof D) ) // line 4
return false;
D other = (D)o; // line 6
return i == other.i;
}
int i;
}
}
我明白了:
C.java:4: illegal generic type for instanceof
if ( !(o instanceof D) )
^
我还得到关于第6行的“未经检查的演员”警告。为什么? o
不是泛型类型 - 它只是普通的Object
。如何通过检查和转换为equals()
的实例来正确实现D
?
注意:显然,此代码示例是我实际代码的缩减版本。 C
和D
的真实类要大得多,D
是private
内部类C
的实现。
仅供参考:真正的D
确实使用了通用参数T
。
答案 0 :(得分:37)
o不是泛型类型 - 它只是一个普通的对象。
这不是问题。问题......以及编译错误的根本原因...... D
是一个泛型类。它是通用的,因为它是泛型类中的非静态嵌套类。其完全限定名称为some.pkg.C<T>.D
。
仅供参考:真正的D确实使用了通用参数T.
可以使用T
这一事实使D
成为通用类。
您无法使用instanceof D
或(D)
的原因是泛型类型擦除。基本上,运行时无法区分(例如)C<String>.D
和C<Integer>.D
的类型。由于它无法做到这一点,因此无法确定instanceof D
是返回true
还是false
还是(D)
应该成功还是抛出ClassCastException
。
一种解决方案是将D
声明为静态。但这不适用于你的“真正的D”,因为静态类不能使用封闭类中的泛型类型参数。你的“FYI”说它就是这样。
另一种解决方案是实例化外部类C
,将实际类型的T
作为java.lang.Class<T>
实例传递给它。然后使用此Class
实例根据需要实现运行时类型检查和强制转换。这可能很麻烦。
第三个解决方案是仔细分析代码,并确定@SuppressWarning注释是否安全,以抑制“不安全的强制转换”等警告。
什么类型的擦除? 'o'直接是Object类型。
实际上Object
是o
变量的声明的类型。实际对象很可能具有其他类型, 类型(例如,如果它是D
实例)将遭受类型擦除。
答案 1 :(得分:7)
如果使内部类静态,则代码编译得很好。
例如:
private static class D{...}
阅读here了解差异。
您也可以尝试o.getClass() != D.class
(当然,在防止o为null之后)
答案 2 :(得分:7)
@StephenC是正确的,问题是D
表示C<T>.D
,这是一个参数化类型。解决方案是使用原始类型或通配符参数化类型:
if ( !(o instanceof C.D) )
或
if ( !(o instanceof C<?>.D) )
答案 3 :(得分:5)
D.class.isInstance(o)
似乎在这里工作。