当前位置: 首页 > 知识库问答 >
问题:

在Java中用泛型方法重写泛型方法

葛炜
2023-03-14

安吉丽卡·兰格(Angelica Langer)在关于仿制药的常见问题解答中说(参见Technicalities.FAQ822):

如果这些方法具有具有不同边界的类型参数,则它们不会重写,因为这些方法的签名不是重写等价的。请记住,类型参数边界是泛型方法签名的一部分。

示例(泛型子类型方法重载泛型超类型方法;不推荐):

class Super {
   public <T> void set( T arg) { ... }
   public <T> T get() { ... }
}
class Sub extends Super {
   public <S extends Number > void set( S arg) { ... } // overloads
   public <S extends Number > S get() { ... }         // overloads
}

我不明白为什么get方法在类Sub中重载。据我所知,这应该是一个编译时错误,因为getSubSuper中具有相同的签名(返回类型不是它的一部分)。

更让我困惑的是,我用来测试代码的IDE(IntelliJ IDEA 14.0.3)突出显示Sub中的get为编译错误,并显示下一条消息:

“Sub”中的“get()”与“Super”中的“get()”冲突;两种方法具有相同的擦除,但都不覆盖另一种方法。

但是当我运行程序时,它编译和执行都没有问题。我认为IntelliJ在分析代码时存在某种缺陷,Angelica在她的FAQ中说的是正确的。但我不明白重点。

共有3个答案

胡墨竹
2023-03-14

据我所知,为什么它是重载而不是重写是因为编译器不认为它是重写等效的。在安吉丽卡·兰格的常见问题中,你可以看到它在讨论为什么重写一个不如预期的方法。

http://www.angelikalanger.com/GenericsFAQ/FAQSections/ProgrammingIdioms.html#FAQ051

总之,方法具有相同的名称和参数,但基于泛型子类型的方法定义为不同的。即使使用覆盖注释,编译器也会将其视为重载方法。在使用泛型时,有一个添加到方法的层,其中泛型类型作为方法的一部分应用,该方法可以唯一地定义泛型类型。

阴永逸
2023-03-14

我认为删除是公开的

它编译并运行:

class B {
    public <T> T get() {
        return null;
    }

}

class A extends B {
    @Override
    public <S> S get() {
        return null;
    }

这没有:

class B {
        public <T> T get() {
            return null;
        }

    }

    class A extends B {
        @Override
        public <S extends Number> S get() {
            return null;
        }

经和歌
2023-03-14

根据JLS,方法签名不包括返回类型,而只包括方法名及其参数的类型。这意味着编译Super和Sub时,编译错误应该返回,因为Sub.get()具有与Super.get()相同的擦除,但不会覆盖或重载Super.get()。它不能重写,因为有界类型X扩展数字不是类型X的子类型,它不能重载,因为返回类型不是方法签名的一部分。在这种情况下,Sub.set重载Super.set。

至于为什么你可以编译和运行它。如果您运行的是Java 6,那么Java 6中有一个已知的错误,它会编译Super和Sub。在Java 7中,这是固定的,是不允许的。

 类似资料:
  • 我正在尝试覆盖子类中从父类继承抽象方法的方法。我正在尝试更改泛型返回类型,但我有点困惑。 基本泛型类: 儿童班: 实施: 我想在其中覆盖参数化方法的子视图类: 这是Eclipse抛出错误消息的地方: 注意类和接口:事件和级别: 以及继承自 的 Model 类 我试图实现的是编写更抽象的代码,因为这些类、接口将被多个类扩展(在我的例子中是不同的视图类型)。这些是抽象类:< code>BaseAdap

  • 来自Java文档:在类C中声明的实例方法m1覆盖在类A中声明的另一个实例方法m2,如果以下所有条件都为真:。。。。。m1的签名是m2签名的子签名(§8.4.2)。 方法m1的签名是方法m2签名的子签名,前提是:m1的签名与m2签名的擦除相同(§4.6)。 是对一个 如果是这样,什么是错的? EDIT1:或者如果我切换通用类型: 这种情况下有什么问题? EDIT2:我知道如何修复它,但我想了解,在这

  • 这是如何编译的: 但这并不是: 它给我以下编译错误: Impl不是抽象的,并且不会覆盖测试中的抽象方法getValue(整数) 错误:名称冲突:Impl中的getValue(T)和测试中的getValue(Integer)具有相同的擦除,但两者都不重写另一个 擦除不能确保t被整数替换吗?那么为什么第二个例子是无效的呢?

  • 我正在做一个体验,尝试用以下方式重写泛型类的方法: 为什么我不能?编译错误是 yGenFun。java:15:错误:对doX的引用不明确,Do中的方法doX(A)和MyGenFun中的方法doX(T)都匹配x.doX(“测试”);^其中A、T是类型变量:在类Do T中声明的extends对象扩展在类MyGenFun 1 error中声明的CharSequence 如果我注释“第1行”,我可以编译代

  • Main.java:12:错误:TextMessage不是抽象的,并且不会覆盖Message类中的抽象方法setContent(T)TextMessage扩展Message{^其中T是类型变量:T扩展方法setContent(T)中声明的Object 1错误

  • 问题内容: 如果在Java中创建泛型类(该类具有泛型类型参数),则可以使用泛型方法(该方法带有泛型类型参数)吗? 考虑以下示例: 正如您对通用方法所期望的那样,我可以使用任何对象调用的实例: 但是,如果我尝试使用 不 指定泛型类型的实例,则无论传入什么,我都会调用返回, 奇怪的是,如果返回类型是通用类,它将编译(例如(实际上,这可以解释-参见下面的答案)): 此外,如果输入通用类,即使仅使用通配符