考虑以下具有非静态内部类的泛型类 Base<ID>
.
public class Base<ID> {
ID id;
public Base(ID id) {
this.id = id;
}
public ID getId() {
return id;
}
protected class BaseInner {
String text = "Inner";
}
protected void method(BaseInner o) {
o.text = "Foo";
}
}
方法 Base.method
采用 BaseInner
类型的参数 . 现在考虑以下派生类 .
public class Sub<ID> extends Base<ID> {
public Sub(ID id) {
super(id);
}
@Override
protected void method(BaseInner o) {
if (o instanceof Sub.SubInner) {
SubInner sub = (SubInner) o; // Why does this cast emit an "unchecked cast" warning
sub.text = "Bar";
sub.value = 1337;
}
}
protected class SubInner extends BaseInner {
Number value = 42;
}
}
类 Sub
派生自 Base
,内部类 SubInner
派生自内部类 BaseInner
. Sub
的泛型类型参数 ID
作为类型参数传递给基类 Base
.
My question: 为什么编译器在 Sub
的覆盖 method
中抱怨从 BaseInner
到 SubInner
的强制转换?
为了理解警告,我尝试构建一个用例,其中 Sub<A>
被调用 Sub<A>
,其中一些 Sub<B>.SubInner
证明了警告 . 但是,如果类型不兼容,我能想到的任何内容(包括 ? extends
和 ? super
)都会在方法调用上发出编译器错误 .
所以我想没有理由在 method
中对未经检查的演员进行警告 . 我错过了什么?
由于方法覆盖发生在 Sub<ID>
实现中,编译器能够将 SubInner
的泛型类型删除为 Sub<ID>.SubInner
. 所以质疑这是 not 重复!
Eclipse编译器警告是
类型安全:取消选中从Base <ID> .BaseInner到Sub <ID> .SubInner的强制转换
如果我使用 Base<ID>.BaseInner
作为方法参数,或者在转换表达式中使用 Sub<ID>.SubInner
,那么waring也不会改变 .
2 回答
这接缝是Eclipse编译器问题 .
Oracle编译器(
javac
)不会在此处省略任何警告 .在这种情况下,未经检查的强制转换意味着您正在从非限定类型转换为泛型类型 .
此行也将生成未经检查的分配警告 .
出现此警告是因为编译器无法在编译时删除强制转换是否安全 .
SubInner实例具有对Sub实例的引用 . 您正在从Base.BaseInner进行强制转换,因此您也从Base转换为Sub <ID> . 因此,您正在收到此警告 .
Edit
解决方案是使用泛型参数 .