下面是一个极简主义的例子
import java.util.List;
public class SomeClass {
interface SuperType {
}
static class SubType implements SuperType {
}
interface SuperTypeProcessor {
void processSubtypesOfSupertype(List<? extends SuperType> superTypes);
List<? extends SuperType> getSubtypesOfSupertype();
}
static class ConcreteSuperTypeProcessor implements SuperTypeProcessor {
// doesn't override!
@Override
public void processSubtypesOfSupertype(List<SubType> superTypes) {
}
// DOES override!
@Override
public List<SubType> getSubtypesOfSupertype() {
return null;
}
}
}
我以为List<SubType>
总是List<? extends SuperType>
的一个子类.也许,它是is,但我需要重新审视凌驾的规则吗?
让我们来看看文档says
在类C中声明的一个实例方法m1覆盖了在类A中声明的另一个实例方法m2,当且仅当以下条件都为真:
C是A.✅的子类.
M1的签名是m2的签名的子签名(§8.4.2).🤔
以下任一项:
M2是公共的、受保护的或在与C或✅相同的包中使用默认访问权限声明的
M1覆盖方法M3(M3不同于M1,M3不同于M2),因此M3覆盖M2.
什么是子签名?
方法m1的签名是方法m2的签名的子签名,如果:
M2具有与M1或❌相同的签名
M1的签名与删除m2的签名相同(第4.6节).🤔
什么是签名擦除?
类型擦除是从类型(可能包括参数类型和类型变量)到类型(从不是参数类型或类型变量)的映射.我们将类型T的擦除写为|T|.擦除映射定义如下:
参数类型(§4.5)G<;T1,...,TN>;的擦除是|G|.
嵌套类型T.C的擦除是|T|.C.
数组类型T[]的擦除是|T|[].
类型变量的擦除(§4.4)是对其最左侧界限的擦除.🤔
所有其他类型的擦除就是类型本身.
这肯定意味着
-
void processSubtypesOfSupertype(List<? extends SuperType>)
被擦除为void processSubtypesOfSupertype(List<SuperType>)
, -
List<? extends SuperType> getSubtypesOfSupertype()
被抹go 成List<SuperType> getSubtypesOfSupertype()
如果是这样,那么为什么List<SubType> getSubtypesOfSupertype()
是有效覆盖?根据我的定义,List<SubType> getSubtypesOfSupertype()
是(类型擦除的)List<SuperType> getSubtypesOfSupertype()
的子签名not
我错过了什么?