Java 为什么仅当基方法包含未使用的类型参数时,重写此泛型方法才起作用?
我在处理Java项目时遇到了一件相当奇怪的事情 我在Java 为什么仅当基方法包含未使用的类型参数时,重写此泛型方法才起作用?,java,generics,overriding,Java,Generics,Overriding,我在处理Java项目时遇到了一件相当奇怪的事情 我在界面中有这个基本方法: public interface Registry<T extends FlakeType<? extends F>, F extends Flake> { @Nullable public <E extends F> T findType(@Nonnull String name); } 对于上下文,Entity扩展Flake,EntityType扩展FlakeT
界面中有这个基本方法
:
public interface Registry<T extends FlakeType<? extends F>, F extends Flake> {
@Nullable
public <E extends F> T findType(@Nonnull String name);
}
对于上下文,Entity
扩展Flake
,EntityType
扩展FlakeType
如您所见,我试图从
EntityType指定此方法的返回类型。类型参数是方法签名的一部分。您可以在以下内容中找到:
如果两个方法或构造函数M和N具有相同的名称,相同的类型参数(如果有)(),则它们具有相同的签名,并且在将N的形式参数类型调整为M的类型参数后,具有相同的形式参数类型
方法m1的签名是方法m2签名的子签名,如果:
m2
具有与m1
相同的签名,或
m1
的签名与m2
签名的擦除()相同
当m1
是m2
的子符号或m2
是m1
的子符号时,两个方法签名m1
和m2
是覆盖等价的
如果注册表中没有类型参数,EntityRegistry
中的方法没有基本接口方法的子签名,因此它不被视为重写。有关编译失败原因的完整说明,请参阅:
类型参数是方法签名的一部分
要使其可编译,只需在EntityRegistry
中指定如下方法:
@Nullable
@Override
EntityType<? extends Entity> findType(@Nonnull String name);
@Nullable
@凌驾
EntityType有效覆盖-两个接口中的findType
方法的签名相同:
<E>findType(String name)
JLS并描述覆盖规则和方法签名在其中的作用。原始代码的一个重要问题是,它不必要地复杂。此外,如果不接受未经检查的强制转换,就无法实现原始的EntityRegistry.findType()
...warning: [unchecked] unchecked cast
return ( EntityType< E > ) new EntityType< >( new Entity( name ) );
^
required: EntityType<E>
found: EntityType<Entity>
where E is a type-variable:
E extends Entity declared in method <E>findType(String)
1 warning
interface EntityRegistry<E>findType(String name)
<E>findType(String name)
findType(String name)
...warning: [unchecked] unchecked cast
return ( EntityType< E > ) new EntityType< >( new Entity( name ) );
^
required: EntityType<E>
found: EntityType<Entity>
where E is a type-variable:
E extends Entity declared in method <E>findType(String)
1 warning
interface Registry< T extends FlakeType<? extends Flake> > {
T findType(String name);
}
interface EntityRegistry< U extends EntityType<? extends Entity> > extends Registry<U> {
@Override
U findType(String name);
}
...
EntityRegistry<EntityType<Entity>> registry = (name) -> { return new EntityType<Entity>(new Entity(name)); };
...
...
Registry<EntityType<Entity>> registry = (name) -> { return new EntityType<Entity>(new Entity(name)); };
...