使用generics返回类型的覆盖方法
假设我有一个定义以下抽象方法的超类
public abstract Class getMainClass();
现在,如果我想在某个子类中覆盖它
public Class getMainClass(){ return Implementation.class; }
我收到有关类型安全和未选中转换的警告:
类型安全:从
getMainClass()
类型返回类型Class
forgetMainClass()
需要未经检查的转换以符合类型SuperFoo
Class
如果
Class
是否属于Class
? 有没有办法正确摆脱警告?
重写方法的返回类型必须是重写方法的返回类型的子类型。
Class
不是Class
的子类型,其中
。 T在这里不得而知。
Class
是Class extends Interface>
的子类型Class extends Interface>
根据子类型规则Class extends Interface>
。
关于通配符的一些子类型规则:
适用于任何类型X.
-
A
是A extends X>
的子类型A extends X>
A extends X>
-
A
是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 <: A extends S> <: A extends T> A <: A super T> <: A super S>
请考虑以下类似于您的方案:
public class SuperFoo { public abstract List getList(); } public class SubFoo extends SuperFoo { private List l = new ArrayList (); public List 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 getMainClass(){ ... }
另一种选择是使SuperFoo
本身具有通用性:
public class SuperFoo { public abstract Class getMainClass(); } public class SubFoo extends SuperFoo { public Class 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 other = a. 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()); } }