【发布时间】:2016-07-28 16:38:08
【问题描述】:
考虑以下具有非静态内部类的泛型类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。
我的问题:为什么编译器会抱怨 Sub 的覆盖 method 中从 BaseInner 到 SubInner 的转换?
为了理解警告,我尝试构建一个用例,其中 Sub<A> 的 method 被一些 Sub<B>.SubInner 调用以证明警告是合理的。但是如果类型不兼容,我能想到的任何东西(包括? extends 和? super)都会在方法调用上发出编译器错误。
所以我想没有理由在method 中警告未经检查的演员表。我错过了什么吗?
由于方法覆盖发生在Sub<ID> 实现中,编译器能够将SubInner 的泛型类型扣除为Sub<ID>.SubInner。所以问题是,这不是重复的!
Eclipse 编译器警告是
类型安全:从 Base
.BaseInner 到 Sub .SubInner 的未经检查的强制转换
如果我使用Base<ID>.BaseInner 作为方法参数,或者我在强制转换表达式中使用Sub<ID>.SubInner,警告不会改变。
【问题讨论】:
-
只是一个猜测,但既然你在 if 语句中使用了
o instanceof Sub.SubInner,你不应该在下面的语句中也使用Sub.SubInner吗? -
我已经尝试过了,并且还在演员阵容中使用了
Sub<ID>.SubInner,但它总是会产生相同的警告。 -
你用的是什么编译器? javac 8 没有任何警告。
-
好的,我猜这是 Eclipse 编译器的问题!如果 Javac 完全不抱怨!我可以按预期投给
SubInner! (没有像Sub<ID>.SubInnernecessary 这样的泛型类型的额外限定) -
@Andy Tuner:这不是重复的。 javac 编译器不会为我的代码发出任何警告!请重新打开问题,以便我们添加正确答案。
标签: java generics compiler-warnings