[英]Overriding method with generic return type
假设我有一个定义以下抽象方法的超类
public abstract <T extends Interface> Class<T> getMainClass();
现在,如果我想在某些子类中覆盖它
public Class<Implementation> getMainClass(){
return Implementation.class;
}
我收到有关类型安全和未选中转换的警告:
类型安全:返回类型
Class<Implementation>
为getMainClass()
从类型SubFoo
需要未经检查的转换,以符合Class<Interface>
从类型SuperFoo
如果<T extends Interface>
Class<Implementation>
是否属于Class<T>
<T extends Interface>
? 有没有办法正确摆脱警告?
重写方法的返回类型必须是重写方法的返回类型的子类型。
Class<Impl>
不是Class<T>
的子类型,其中<T extends Interface>
。 T在这里不得而知。
Class<Impl>
是Class<? extends Interface>
的子类型Class<? extends Interface>
根据子类型规则Class<? extends Interface>
。
关于通配符的一些子类型规则:
适用于任何类型X.
A<X>
是A<? extends X>
的子类型A<? extends X>
A<? extends X>
A<X>
是A<? super X>
的子类型A<? super X>
A<? super X>
如果S
是T
子类型
A<? extends S>
A<? extends S>
是A<? extends T>
的子类型A<? extends T>
A<? extends T>
A<? super T>
A<? super T>
是A<? super S>
的子类型A<? super S>
A<? super S>
更简洁,( <:
表示“是”的子类型“)
A<S> <: A<? extends S> <: A<? extends T>
A<T> <: A<? super T> <: A<? super S>
请考虑以下类似于您的方案:
public class SuperFoo {
public abstract <T extends Interface> List<T> getList();
}
public class SubFoo extends SuperFoo {
private List<Implementation> l = new ArrayList<Implementation>();
public List<Implementation> getList() {
return l;
}
public void iterate() {
for (Implementation i: l) ...;
}
}
SubFoo subFoo = new SubFoo();
SuperFoo superFoo = subFoo;
superFoo.getList().add(new AnotherImplementation()); // Valid operation!
subFoo.iterate(); // Unexpected ClassCastException!
在这种情况下,未经检查的转换警告会警告您可能出现意外的ClassCastException
。
但是,在你的情况下,当返回类型是Class<...>
,它不是问题(据我所知),所以你可以合法地抑制警告:
@SuppressWarnings("unchecked")
public Class<Implementation> getMainClass(){ ... }
另一种选择是使SuperFoo
本身具有通用性:
public class SuperFoo<T extends Interface> {
public abstract Class<T> getMainClass();
}
public class SubFoo extends SuperFoo<Implementation> {
public Class<Implementation> getMainClass() { ... }
}
对于另一个(也许是最好的)选项,请参阅Stas Kurilin的回答。
尝试这个
public abstract Class<? extends Interface> getMainClass();
通过这样的警告重新组织的例子 java尝试防止像这样的情况
class OtherImpl implements Interface{
}
A a = new B();//where A - your abstract class and B - implementation
Class<OtherImpl> other = a.<OtherImpl>getMainClass();//some broken think, But _without_ runtime exception
正如@axtavt提到的例子被打破了。 我重组了它。
为什么你想要像public abstract Class<? extends Interface> getMainClass();
public abstract Class<? extends Interface> getMainClass();
而不是public abstract Interface getMainClass();
?
我想你可以简单地返回一个Interface
实例,然后,如果调用者想要访问底层运行时类,只需在返回的对象上调用getClass()
即可。
从本质上讲,我认为你可以做到
public InterfaceImpl implements Interface {
// ...
};
public abstract class A {
public abstract Interface getMainClass();
// ...
}
public class AImpl {
return new InterfaceImpl();
}
public class Main {
public static void main(String[] args) {
AImpl aImpl = new AImpl();
Interface i = aImpl.getMainClass();
System.out.println(i.getClass());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.