考虑以下具有非静态内部类的泛型类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
。 ID
的泛型类型参数Sub
作为类型参数传递给基类Base
。
我的问题:为什么编译器会抱怨BaseInner
中SubInner
method
中Sub
到method
的演员表?
要了解警告,我尝试构建一个用例,其中Sub<A>
的{{1}}被调用,其中一些Sub<B>.SubInner
证明了警告的合理性。但是,如果类型不兼容,我能想到的任何内容(包括? extends
和? super
)都会在方法调用上发出编译器错误。
所以我猜我没有理由在method
中对未经检查的演员表示警告。我错过了什么吗?
由于方法覆盖发生在Sub<ID>
实现中,编译器能够将SubInner
的泛型类型推断为Sub<ID>.SubInner
。所以质疑这是不重复!
Eclipse编译器警告是
类型安全:取消选中从Base&lt; ID&gt; .BaseInner到Sub&lt; ID&gt; .SubInner
的强制转换
如果我使用Base<ID>.BaseInner
作为方法参数,或者在演员表达式中使用Sub<ID>.SubInner
,那么waring也不会改变。
答案 0 :(得分:1)
这接缝是Eclipse编译器问题。
Oracle编译器(javac
)不会在此处省略任何警告。
答案 1 :(得分:0)
在这种情况下,未经检查的强制转换意味着您正在从非限定类型转换为泛型类型。
Set<String> set = new HashSet();
此行也会生成未经检查的分配警告。
出现此警告是因为如果编译时编译器是安全的,编译器无法扣除。
SubInner实例具有对Sub实例的引用。您正在从Base.BaseInner进行强制转换,因此您也从Base转换为Sub&lt; ID&gt;。因此,您正在收到此警告。
修改强>
解决方案是使用通用参数。
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(Base<ID>.BaseInner o) {
o.text = "Foo";
}
}
public class Sub<ID> extends Base<ID> {
public Sub(ID id) {
super(id);
}
@Override
protected void method(Base<ID>.BaseInner o) {
SubInner sub = (SubInner) o;
sub.text = "Bar";
sub.value = 1337;
}
protected class SubInner extends BaseInner {
Number value = 42;
}
}