使用generics返回类型的覆盖方法

假设我有一个定义以下抽象方法的超类

public abstract  Class getMainClass(); 

现在,如果我想在某个子类中覆盖它

 public Class getMainClass(){ return Implementation.class; } 

我收到有关类型安全和未选中转换的警告:

类型安全:从getMainClass()类型返回类型Class for getMainClass()需要未经检查的转换以符合类型SuperFoo Class

如果 Class是否属于Class ? 有没有办法正确摆脱警告?

重写方法的返回类型必须是重写方法的返回类型的子类型。

Class不是Class的子类型,其中 。 T在这里不得而知。

ClassClass的子类型Class 根据子类型规则Class


关于通配符的一些子类型规则:

适用于任何类型X.

  • AA的子类型A A

  • AA的子类型A A

如果ST子类型

  • A AA的子类型A A

  • A AA的子类型A A

更简洁,( <:表示“是”的子类型“)

 A <: A <: A A <: A <: A 

请考虑以下类似于您的方案:

 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 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 getMainClass(); public abstract Class 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()); } }