如何覆盖返回<t extends =“”someclass =“”> T </t>的方法

时间:2014-04-02 20:14:04

标签: java

我在ClassA中有一个受保护的抽象方法:

protected abstract <T extends Class1> T methodName();

当我在子类ClassB中重写此方法时,我不断收到类型安全警告:类型ClassB中的methodName()的返回类型Class2需要未经检查的转换以符合类型ClassA中的T. 这里,Class2扩展了Class1

如果不使用@SuppressWarnings(&#34;未经检查&#34;),我怎么能得到这个警告?

2 个答案:

答案 0 :(得分:0)

ClassA中的这种方法意味着您可以为{em>任何扩展methodName()T致电Class1。这意味着您无法覆盖它以返回扩展T的某些特定 Class1

相反,您必须使T成为该类的类型参数:

abstract class ClassA<T extends Class1> {
   protected abstract T methodName();
}
class ClassB extends ClassA<Class2> {
   @Override protected Class2 methodName() {...}
}

答案 1 :(得分:0)

  

如何在不使用@SuppressWarnings(“未选中”)的情况下获取此警告

只有以不同的方式做到这一点。你在做什么本质上是不安全的。从编译器消息中,我们可以推断出你拥有的是这样的东西:

class Class1 {}
class Class2 extends Class1 {}

abstract class ClassA {
    protected abstract <T extends Class1> T methodName();
}

class ClassB extends ClassA {
    @Override
    protected Class2 methodName() {
        return new Class2();
    }
}

这是允许的,因为与擦除的奇怪交互,<T extends Class1>的擦除是Class1所以允许重写以返回具体的子类型。 (这是'覆盖等效'。)

这是不安全的,因为methodNameClassA的返回类型是通用的,因此由调用者确定。它可以是Class1Class1的任何子类型。这将导致ClassCastException:

class Class3 extends Class1 {}

ClassA actuallyB = new ClassB();
Class3 c3 = actuallyB.<Class3>methodName();

这会导致Class2投放到Class3

相反,您可以将返回类型声明为该类的参数(已经建议):

abstract class ClassA<T extends Class1> {
    protected abstract T methodName();
}

或者根本不使用泛型:

abstract class ClassA {
    protected abstract Class1 methodName();
}

class ClassB extends ClassA {
    @Override
    protected Class2 methodName() {
        return new Class2();
    }
}

(如果您不知道,Java允许您覆盖以返回子类型。)通常,除非您确实需要,否则不应使用泛型。