什么是“覆盖等价”,它与@Override有什么关系?
读取@Override
注释的Javadoc ,我遇到了以下规则:
如果使用此注释类型注释方法,则编译器需要生成错误消息,除非至少满足下列条件之一:
- 该方法会覆盖或实现在超类型中声明的方法。
- 该方法的签名覆盖等效于Object中声明的任何公共方法。
我对第一点很清楚,但我不确定第二点。
“覆盖等价”是什么意思? 在这方面, Object
公共方法如何特殊? 为什么这不属于第一个标准?
更新说明:这仅适用于Java 7文档。 Java 6 doc没有提到有关覆盖等价的任何内容。 为什么要改变?
更新:
在咨询了JLS( 第8.4.2节 )之后,我发现了以下对覆盖等价的解释:
方法
m1
的签名是方法m2
的签名的子签名,如果:
m2
与m1
具有相同的签名,或m1
的签名与m2
签名的擦除( §4.6 )相同。如果
m1
是m2
签名或m2
是m1
签名,则两个方法签名m1
和m2
是覆盖等价的 。
据我所知,这回答了第一个问题(“它是什么意思?”)和第三个问题(“为什么第一个条件不包括这个?”)。
如果我理解正确(如果我不理解,请通知我!),只有一种情况,两种方法是覆盖等价的, 并且不属于原始问题的第一个条件。 当子类方法的签名的擦除与超类方法的签名相同时,情况就是这种情况,而不是相反。
因此,当我们在尝试“覆盖” Object
类的公共方法时尝试添加类型参数时,原始问题的第二个条件才会发挥作用。 我尝试了以下简单示例来测试它,使用未使用的类型参数:
public class Foo { @Override public boolean equals(Object obj) { return true; } }
当然,这个类不编译,因为该方法实际上并没有覆盖equals
方法,因此与它发生冲突。 但是我仍然收到使用@Override
注释的错误。 假设这是@Override
使用的第二个条件的有效示例,我错了吗? 或者编译器是否生成此错误, 尽管不需要 ?
这样做的原因是允许您在接口中使用@Override
注释,这些注释不从Object
inheritance,而是从Object
隐式声明所有公共方法(请参阅JLS第9.2节接口成员 )。 因此,您可以声明如下界面:
interface Bar { @Override int hashCode(); }
但是,您不能声明以下接口:
interface Quux { @Override Object clone(); }
因为clone()
方法没有在接口中隐式声明(它不是public
)。
这在JLS第9.6.3.4节@Override中描述( @Override的Javadoc仍然引用旧的节号)
您的问题基本上是一个设计问题,JLS解释了它:
“子签名的概念旨在表达两个方法之间的关系,这两个方法的签名不相同,但是其中一个可以覆盖另一个。具体来说,它允许一个方法,其签名不使用generics类型来覆盖该方法的任何泛化版本这很重要,这样图书馆设计师就可以独立于定义库的子类或子接口的客户端自由地生成方法。“
您的代码不是一个有效的示例,请参阅下面的代码:
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 List test(Collection t) { return null; } }
重点是擦除后超类和子类的签名应该相同。
编辑:当我们谈论覆盖等价时,父类应该有generics方法,子类应该有非generics方法。 下面是一个例子来解释这个.Below代码不起作用,因为子类具有generics方法。 暂时假设java允许,然后main方法中的调用将始终失败:
class A{ public int compareTo(Object o){ return 0; } } class B extends A implements Comparable{ 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())
。 因此,如果父类具有非generics方法,则java将不允许子类具有generics方法。 因此,您无法为对象类定义重写等价方法。
希望澄清一下。
我使用http://lists.seas.upenn.edu/pipermail/types-list/2006/001091.html这个post作为参考,它有更多的细节。