什么是"覆盖等价",它与@Override有什么关系?

Oct*_*ron 16 java overriding annotations language-design method-signature

的Javadoc@Override注释,我遇到了以下规则:

如果使用此批注类型对方法进行批注,则编译器需要生成错误消息,除非至少满足下列条件之一:

  • 该方法会覆盖或实现在超类型中声明的方法.
  • 该方法的签名覆盖等效于Object中声明的任何公共方法.

我对第一点很清楚,但我不确定第二点.

"覆盖等价"是什么意思?Object在这方面,公共方法有何特别之处?为什么这不属于第一个标准?

更新说明:这仅适用于Java 7文档.在Java 6的文档不说的覆盖等价什么.为什么要改变?


更新:

在咨询了JLS(第8.4.2节)之后,我发现了以下对覆盖等价的解释:

的方法的签名m1是一个子签名的方法的签名m2,如果任一:

  • m2具有相同的签名m1,或
  • 签名与签名m1的擦除(§4.6)相同m2.

两个方法签名m1并且m2覆盖等效的,如果它们m1是子签名m2或是m2其子签名m1.

据我所知,这回答了第一个问题("它是什么意思?")和第三个问题("为什么第一个条件不包括这个?").

如果我理解正确(如果我没有请通知我!),只有一种情况,两种方法是覆盖等价的,并且不属于原始问题的第一个条件.当子类方法的签名的擦除与超类方法的签名相同时,情况就是这种情况,而不是相反.

因此,当我们在尝试"覆盖"类的公共方法时尝试添加类型参数时,原始问题的第二个条件才会发挥作用Object.我尝试了以下简单示例来测试它,使用未使用的类型参数:

public class Foo {
    @Override
    public <T> boolean equals(Object obj) {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,这个类没有编译,因为该方法不实际覆盖的equals方法,因此与它相撞.但是我仍然收到使用@Override注释的错误.假设这是第二个@Override使用条件的有效示例,我错了吗?或者编译器是否生成此错误,尽管不需要

Did*_*r L 6

这样做的原因是允许您@Override在接口中使用注释,该注释不从中继承Object但隐式声明所有公共方法Object(请参阅JLS第9.2节接口成员).因此,您可以声明如下界面:

interface Bar { @Override int hashCode(); }
Run Code Online (Sandbox Code Playgroud)

但是,您不能声明以下接口:

interface Quux { @Override Object clone(); }
Run Code Online (Sandbox Code Playgroud)

因为该clone()方法未在接口中隐式声明(它不是public).

这在JLS第9.6.3.4节@Override中描述(Javadoc @Override仍然引用旧的节号)


Lok*_*esh 5

你的问题基本上是一个设计问题,JLS解释了它:

"子签名的概念旨在表达两个方法之间的关系,这两个方法的签名不相同,但是其中一个可以覆盖另一个.具体来说,它允许一个方法,其签名不使用泛型类型来覆盖该方法的任何泛化版本这很重要,因此图书馆设计师可以独立于定义图书馆子类或子接口的客户端自由地生成方法."

您的代码不是一个有效的示例,请参阅下面的代码:

public class SubSignatureTest extends SignatureTest {

    @Override
    public List test(Collection p) {
        return null;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub

    }

}

class SignatureTest {

    public <T> List<T> test(Collection<T> t) {
        return null;

    }
}
Run Code Online (Sandbox Code Playgroud)

重点是擦除后超类和子类的签名应该相同.

编辑:当我们谈论覆盖等价时,父类应该有泛型方法,子类应该有非泛型方法.下面是一个例子来解释这个.Below代码不起作用,因为子类具有泛型方法.暂时假设java允许,然后main方法中的调用将始终失败:

class A{
       public int compareTo(Object o){
               return 0;
       }
}

class B extends A implements Comparable<B>{
       public int compareTo(B b){
               return 0;
       }

       public static void main(String[] argv){
               System.out.println(new B().compareTo(new Object()));
       }
}
Run Code Online (Sandbox Code Playgroud)

在B类方法编译后会像这样:

public int compareTo(Object x){
    return compareTo((B)x);
  }
Run Code Online (Sandbox Code Playgroud)

这意味着总是错误:new B().compareTo(new Object()).因此,如果父类具有非泛型方法,则java将不允许子类具有泛型方法.因此,您无法为对象类定义重写等价方法.

希望澄清一下.

我使用帖子http://lists.seas.upenn.edu/pipermail/types-list/2006/001091.html作为参考,它有更多的细节.

  • 也许我误解了你,但"你不能创建对象类方法的覆盖等价方法"和"该方法有一个覆盖的签名 - 等同于在Object中声明的任何公共方法的签名"似乎是矛盾的. (2认同)