TL;DR
在我看来,这本书的措辞在这里并没有很好地结合在一起。重载是根据覆盖等价性的否定来定义的,根据金龙生 (8.4.9) http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.9(释义:如果存在两个同名的方法,但不等效重写,那么它们就会重载)。
但给出的例子是方法是NOT覆盖等效,但是DO由于其他原因导致编译时错误(名称冲突 - 中指定的特定编译时错误JLS 8.4.8.3 http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.3),因此不要超载。
Preamble
据我了解,您提出的问题是关于这句话的确切语义的:
“...或者m1的签名与m2签名的擦除相同”
结合
m1 和 m2 是覆盖等效的,当且仅当 m1 是 m2 的子签名或 m2 是 m1 的子签名。
你的书暗示这应该解释为
"or the 的擦除m1的签名与m2签名的擦除相同"
(添加的单词以粗体斜体显示)。
而你会把它解释为
“或 m1 的签名(无需擦除) 与m2签名的擦除相同"
你的解释是正确的。我不认为这句话有歧义,因此我认为用第一种方式解释它(即erasure两个签名相同)是不正确的。你可能会喜欢看看这个相关的答案 https://stackoverflow.com/a/21690951/838992在这里增加我的观点的分量(我发现它是因为我也想检查我的理解)。
回答(不过……)
您引用的书中的部分实际上是在尝试描述超载。
现在 - 当考虑超载时 -JLS(8.4.9)说 http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.9 that:
如果一个类的两个方法(无论是在同一个类中声明,还是都由一个类继承,或者一个声明一个继承)具有相同的名称,但签名不是重写等效的,则该方法名称被称为超载。
至少从 Java 6 开始,这一点是一致的。这就是两者之间的联系所在override-equivalent
和超载源于。
好的 - 所以你的方法会重载,因为它们不是严格覆盖等价的。正确的?
Wrong.
因为就在该部分的上方在 8.4.8.3 中,JLS http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.8.3放入特定的编译时错误:
如果类型声明 T 具有成员方法 m1 并且存在 T 中声明的方法 m2 或 T 的超类型,并且满足以下所有条件,则会出现编译时错误:
这就是您的示例中的场景。就在该部分的下方,它阐明了为什么有必要:
这些限制是必要的,因为泛型是通过擦除来实现的。上面的规则意味着在同一个类中声明的具有相同名称的方法必须具有不同的擦除。它还意味着类型声明不能实现或扩展同一泛型接口的两个不同调用。
边注
书中的示例很奇怪,因为 Java 不允许重写静态方法(而子类中方法的签名可能会在超类中隐藏该方法)。在我看来,这使得不覆盖等效的概念对于学习者来说有点棘手。但是,您可以删除static
并且仍然可以看到他们试图展示的效果。