假设我有像这样的简单类
public interface Something{
public void doSomtehing()
}
class A{
public int getAVal(){
return 0;
}
}
class AWithSomething extends A implements Something{
public void doSomething{
//in fact do nothing, HAHA
}
}
abstract class B{
public abstract <T extends A & Something> T getAWithSomething()
}
class C extends B{
//allowed??? gives warnig about unchecked conversion
public A getAWithSomething {
return new A();
}
}
class D extends B{
//same unchecked warning
public AWithSomething getAWithSomething(){
return new AWithSomething();
}
}
C c = new C();
//not implemented but seems valid
c.getAWithSomething().doSomething();
D d = new D();
d.getAWithSomething().doSomething();
所以我的主要问题是:为什么编译器允许类C
只返回A而不检查它是否在编译时实现接口?
class C extends B{
//not allowed!
public Something getAWithSomething {
return new Something(){
doSomething(){}
};
}
}
答案 0 :(得分:1)
JLS称之为migration compatibility。应允许库实现者在不破坏客户端(B
)的情况下生成其API(C
)。事实上,可以用B
替换List
,用getAWithSomething()
替换get(int)
,用自定义C
替换List
- 例如apache commons FixedSizeList
。
方法签名中的类型变量将被删除为原始类或接口类型。 T
中的类型变量B.getAWithSomething()
将被删除到其最左边的A
。迁移兼容性基于生成的方法签名A getAWithSomething()
。这意味着重写getAWithSomething()
的子类必须声明返回类型A
或其子类型。
请注意,您会收到一条警告,说“小心,您将A
作为A&Something
传递出去,这可能会出错”。它可以:在返回的doSomething()
上调用A
会抛出ClassCastException
,因为A
无法投放到Something
。