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

时间:2013-04-25 05:57:00

标签: java annotations override language-design method-signature

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

  

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

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

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

“覆盖等效”是什么意思? Object的公共方法在这方面有何特殊之处?为什么这不属于第一个标准?

更新说明:这仅适用于Java 7文档。 Java 6 doc没有提及覆盖等价的任何内容。为什么要改变?


更新

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

  

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

     
      
  • m2m1
  • 具有相同的签名   
  • m1的签名与m2签名的删除(§4.6)相同。
  •   
     

两个方法签名m1m2覆盖等效 iff m1是一个   m2m2的子签名是m1的子签名。

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

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

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

public class Foo {
    @Override
    public <T> boolean equals(Object obj) {
        return true;
    }
}

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

2 个答案:

答案 0 :(得分:6)

这样做的原因是允许您在接口中使用@Override注释,这些注释不从Object继承,而是从Object隐式声明所有公共方法(参见{{3} }})。因此,您可以声明如下界面:

interface Bar { @Override int hashCode(); }

但是,您不会被允许声明以下界面:

interface Quux { @Override Object clone(); }

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

JLS section 9.2 interface members中描述了这一点(@Override的Javadoc仍然引用旧的节号)

答案 1 :(得分: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;

    }
}

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

编辑: 当我们谈论重写等价时,父类应该有泛型方法,子类应该有非泛型方法。下面是一个例子来解释这个.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()));
       }
}

在编译后,B类方法将如下所示:

public int compareTo(Object x){
    return compareTo((B)x);
  }

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

希望澄清。

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