我在从事Java项目时遇到了一件非常奇怪的事情。
我在界面中有这个基本方法:
public interface Registry<T extends FlakeType<? extends F>, F extends Flake> {
@Nullable
public <E extends F> T findType(@Nonnull String name);
}
显然,类型参数E
完全没用,因为它既不用于返回类型也不用于参数。我的IDE也通知了我这一点。
我还有一个扩展注册表的接口:
public interface EntityRegistry extends Registry<EntityType<? extends Entity>, Entity> {
@Nullable
@Override
<E extends Entity> EntityType<E> findType(@Nonnull String name);
}
对于上下文,Entity
扩展Flake
,EntityType
如您所见,我正在尝试从
EntityType指定此方法的返回类型
逻辑上,<代码>?扩展实体和扩展实体在这种情况下的含义是相同的,因为扩展实体没有其他限制或类似的限制,因此基本上也是扩展实体类型的通配符。
这很好用。
然而,我注意到IDE(Intellij)通知我
类型参数
E
从不使用。
这让我觉得我可以删除它,因为它显然是无用的,并且与返回值或任何参数都没有任何关系。
重写方法提供了自己的类型参数,它与基方法中同名的无用类型参数没有任何关系。还是有?
因为一旦我将基本方法更改为:
@Nullable
public T findType(@Nonnull String name);
无法再以相同的方式覆盖它:
与注册表中的findType(String)冲突;这两种方法具有相同的擦除,但都不重写另一种方法。实体注册表中的
findType(String)
我现在的问题是:
>
当重写方法想要指定返回值泛型类型时,为什么Java在base方法中需要一个无用的类型参数?重写方法提供的参数不应该足够吗?
为什么在第二种情况下重写不起作用?除了使用另一个类型参数而不是显式通配符之外,签名与第一种情况完全相同,这难道不应该工作吗?但既然这意味着相同的事情,那么区别是什么呢?
我肯定我对泛型做了一些错误的假设,这就是为什么我对此感到困惑。你能帮我澄清一下吗?
提前感谢!
有效覆盖-findType方法的签名在两个接口中都是相同的:
<E>findType(String name)
无效重写-由于删除了类型参数,签名变得不同:
<E>findType(String name)
findType(String name)
JLS§8.4.8.1和§8.4.2描述了覆盖规则以及方法签名在其中的作用。
请参阅Jorn Vernee的答案,了解其未能编译的原因的完整描述:
类型参数是方法签名的一部分。
要进行编译,只需在EntityRegistry中指定如下方法:
@Nullable
@Override
EntityType<? extends Entity> findType(@Nonnull String name);
这与原始版本一致,因为实际上没有定义,即
。
类型参数是方法签名的一部分。您可以在JLS§8.4.2中找到:
如果两个方法或构造函数M和N具有相同的名称、相同的类型参数(如果有)(§8.4.4),则它们具有相同的签名,并且在将N的形式参数类型调整为M的类型参数后,具有相同的形式参数类型。
方法m1的签名是方法m2
签名的子签名,如果:
>
m1的签名与m2签名的擦除(§4.6)相同。
当m1是m2的子签名或m2是m1的子签名时,这两个方法签名是覆盖等价的。
如果注册表中没有type参数,EntityRegistry中的方法没有基接口方法的子签名,因此它不被视为重写。
为什么<代码>列表 我不明白编译器的消息和编译错误的原因。 返回类型没有问题:
我无法编译一个需要从抽象类超类型重写方法的方法,该类超类型使用泛型作为其中一个参数。编译器抱怨扩展类的setRef()方法没有重写超类型中的方法。 父摘要类: 参考是: 而Interf是: 扩展子类(setRef()不编译): 我也尝试过使用通配符,但收到了相同的错误。使用通配符时,抽象类“setRef()是: 扩展类setRef()是: 甚至: 我能让它编译的唯一方法是,如果扩展类“setRef
安吉丽卡·兰格(Angelica Langer)在关于仿制药的常见问题解答中说(参见Technicalities.FAQ822): 如果这些方法具有具有不同边界的类型参数,则它们不会重写,因为这些方法的签名不是重写等价的。请记住,类型参数边界是泛型方法签名的一部分。 示例(泛型子类型方法重载泛型超类型方法;不推荐): 我不明白为什么方法在类中重载。据我所知,这应该是一个编译时错误,因为在和中具有相
问题内容: 我有一个抽象类 Monitor.java ,它由类 EmailMonitor.java 子类 化 。 方法: 在 Monitor.java中 定义,并且必须在 EmailMonitor.java中 覆盖。 我目前在 EmailMonitor.java中 重写了如下方法: 但是,这会产生编译时错误: 是的子类,因此(至少在我看来)以这种方式覆盖它是很有意义的。看到编译器对我的逻辑不满意,
我正在做一个体验,尝试用以下方式重写泛型类的方法: 为什么我不能?编译错误是 yGenFun。java:15:错误:对doX的引用不明确,Do中的方法doX(A)和MyGenFun中的方法doX(T)都匹配x.doX(“测试”);^其中A、T是类型变量:在类Do T中声明的extends对象扩展在类MyGenFun 1 error中声明的CharSequence 如果我注释“第1行”,我可以编译代
get1方法工作正常,但get2存在编译错误: > 类型A.B的方法get2(集合)必须重写或实现超类型方法 只有带有泛型的参数才会出现此错误<代码>get3编译,但当然有一个警告: > 显然还有其他方法可以解决这个问题,但在我的理解中,这应该是一个法律优先事项,我的问题更多的是为什么会有这个编译错误。提前谢谢! 编辑: 对不起,我的例子不够清楚。因此,这里有一个新的答案来回应你的一些观点。 与上