我在ClassA中有一个受保护的抽象方法:
protected abstract <T extends Class1> T methodName();
当我在子类ClassB中重写此方法时,我不断收到类型安全警告:类型ClassB中的methodName()的返回类型Class2需要未经检查的转换以符合类型ClassA中的T. 这里,Class2扩展了Class1
如果不使用@SuppressWarnings(&#34;未经检查&#34;),我怎么能得到这个警告?
答案 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
所以允许重写以返回具体的子类型。 (这是'覆盖等效'。)
这是不安全的,因为methodName
中ClassA
的返回类型是通用的,因此由调用者确定。它可以是Class1
或Class1
的任何子类型。这将导致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允许您覆盖以返回子类型。)通常,除非您确实需要,否则不应使用泛型。