两个擦除方法相同的擦除方法不需要重写等价(或者它们的签名不是它们之间的子签名)? [英] Two methods with same erasure aren't necessary override-equivalent (or they signatures aren't subsignatures between them)?
问题描述
我正在阅读jdk6的令人难以置信的书java程序员指南,以及关于通用重写的一节。在它上面描述了subsignature和override-equivalent,并且描述了一些与我引用的重写相同的例子:
给出以下三个泛型方法声明在课堂上:
static< T>无效合并(MyStack< T> s1,MyStack< T> s2){/*...*/}
静态< T> void merge(MyStack< T> s1,MyStack<?extends T> s2){/*...*/}
static< T> void merge(MyStack< T> s1,MyStack<?super T> s2){/*...*/}
,所有这三种方法的签名是:
merge(MyStack,MyStack)
也就是说,方法的签名是覆盖等价的,因此这些方法
不会超载。
我并不完全同意这些方法是重写等价的,事实上我认为这些方法有一个通过擦除命名冲突,但没有一个是另一个的subignature ...可能是我错了,所以我想要在这个一些光。
子签名的定义使我认为它们之间不存在subsign。
在JSL 6#8.4中。 2方法签名( http:// docs。 oracle / javase / specs / jls / se6 / html / classes.html#8.4.2 )如果它们具有相同的名称和参数类型,则具有相同的签名。 他们。具有相同数量的形式参数(可能为零) 它们具有相同数量的类型参数(可能为零) 令
如果满足以下所有条件,则两个方法或构造函数声明M和N具有相同的参数类型:
< A1,...,An>
为M的正式类型参数并让< B1,...,Bn>
是N的形式类型参数。在将N的类型中的每个Bi出现重命名为Ai后,相应类型变量的边界以及M和N的参数类型分别为相同。
方法m1的签名是方法m2的签名的子签名,如果
m2与m1具有相同的签名,或者m1的签名与m2的签名的删除相同b
$ p code> ...
如果m1是m2的子签名或m2是m1的子签名,则两个方法签名m1和m2是替代等效项。
在JSL 8#8.4.2中。方法签名( http:/ /docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.2 )
如果两个方法或构造函数M和N具有相同的名称,相同的类型参数(如果有)(§8.4.4),并且在修改N的形式参数类型到M的类型参数,相同的形式参数类型。
方法m1的签名是方法m2的签名的子签名,如果: p>
- m1的签名与m2的签名的擦除相同。
m2与m1具有相同的签名,或者
两个方法签名m1和m2是如果m1是m2或m2的子签名是m1的子签名,则覆盖等效项。
编辑1
简单来说,我的疑问是,从删除子签名的定义中,我明白
一个没有删除的签名等于从另一个签名删除而不是
擦除之后的两个签名都是相等的......其微妙而重要的
(顺便说一下,覆盖等价定义基于子签名定义,这就是为什么我要求)
TL; DR
在我看来,这本书并没有很好地融合在一起。重载的定义是根据否定等效重写来定义的,如 JLS(8.4.9)(释义:如果存在两个名称相同的方法,但不是覆盖等效的,则它们将超载)。
但给出的例子是 NOT 覆盖等值的方法,但是 DO 由于其他原因导致编译时错误(名称冲突 - JLS 8.4.8.3 ),因此不会超负荷。
据我所知,你提出了一个关于这个句子的确切语义的问题:
...或者m1的签名与m2的签名的删除相同
结合
m1是m2或m2的子签名是m1的子签名。
您的书意味着这应该被解释为
或m1的 签名的 擦除与m2签名的擦除相同
(以斜体添加的单词)。
它作为
或m1( 没有删除 )的签名是与删除m2的签名相同
您的解释是正确的。我不认为该句子是不明确的,因此我认为以第一种方式解释(即两个签名的 擦除 是相同的)是不正确的。你可能想看看这个相关的答案来增加我的意见在这里的重量(我发现它,因为我想检查我的理解也是如此)。
回答(然而...)
<你引用的这部分内容实际上是试图描述超载。
现在 - 当考虑重载 - that:
如果一个类的两个方法(无论是在同一个类中声明的,还是由一个类继承的,或者一个声明的和一个继承的)具有相同的名称,但签名不是与覆盖等效的,那么方法名称被超载。
至少从Java 6开始,这一直是一致的。这就是覆盖等价
和重载源于。
确定 - 所以你的方法会超载,因为它们不是严格的覆盖等值。对吗?
错误。
m2可以从T访问。
m1的签名不是子签名(§8.4 2)签名m2。
m1或某些方法m1覆盖(直接或间接)的签名与m2的签名具有相同的删除或者一些方法m2覆盖(直接或间接)。
这是场景在你的例子中。在该节的下面,它阐明了为什么它是必要的:
这些限制是必要的,因为泛型是通过擦除实现的。上面的规则意味着在相同类中声明的具有相同名称的方法必须具有不同的擦除。这也意味着类型声明不能实现或扩展同一个通用接口的两个不同的调用。 / h3>
本书中的例子很奇怪,因为Java不允许重写静态方法(相反,子类中方法的签名可能会隐藏在超类中) 。这使得在我看来,对于学习者来说,不被覆盖的概念相当有点棘手。但是,您可以删除
static
,但仍然可以看到他们试图演示的效果。Im reading the incredible book "a programmer's guide to java scjp certification" for jdk6 and theres a section about generic overriding. On it is described subsignature and override-equivalent and describes some examples of override-equivalent that I quote:
Given the following three generic method declarations in a class:
static <T> void merge (MyStack<T> s1, MyStack<T> s2) { /*...*/ }
static <T> void merge (MyStack<T> s1, MyStack<? extends T> s2) { /*...*/ }
static <T> void merge (MyStack<T> s1, MyStack<? super T> s2) { /*...*/ }
After erasure, the signature of all three methods is:
merge(MyStack, MyStack)
i.e., the signatures of the methods are override-equivalent, hence these methods are not overloaded.Im not totally agree that these methods are override-equivalent , in fact i think the methods have a "name clash by erasure" but none is subsignature of the other one… possibly im wrong so i want some light on this.
The definitions of subsignature makes me think that they arent subsignatures between them.
In JSL 6 #8.4.2 Method Signature (http://docs.oracle.com/javase/specs/jls/se6/html/classes.html#8.4.2)
Two methods have the same signature if they have the same name and argument types. Two method or constructor declarations M and N have the same argument types if all of the following conditions hold:
They. have the same number of formal parameters (possibly zero)
They have the same number of type parameters (possibly zero)
Let
<A1,...,An>
be the formal type parameters of M and let<B1,...,Bn>
be the formal type parameters of N. After renaming each occurrence of a Bi in N's type to Ai the bounds of corresponding type variables and the argument types of M and N are the same.The signature of a method m1 is a subsignature of the signature of a method m2 if either m2 has the same signature as m1, or the signature of m1 is the same as the erasure of the signature of m2
...
Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.
In JSL 8 # 8.4.2. Method Signature (http://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.2)
Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (§8.4.4), and, after adapting the formal parameter types of N to the the type parameters of M, the same formal parameter types.
The signature of a method m1 is a subsignature of the signature of a method m2 if either:
m2 has the same signature as m1, or
the signature of m1 is the same as the erasure of the signature of m2.
Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.
EDIT 1
To put it simple, my doubt is that from the subsignature definition in respect to erasure i understand that "one signature without erasure is equal to the erasure from the other signature".. and not that "both signatures after erasure are equal" .. its subtle but important (by the way, the override-equivalent definition is based on subsignature definition, thats why i ask in terms of subsignatures)
解决方案TL;DR
The wording of the book does not hang together very well here, in my opinion. Overloading is defined in terms of a negation of override-equivalence, as per the JLS (8.4.9) (paraphrasing: if two methods with the same name exist but are not override-equivalent, then they will overload).
But the example given is one where the methods are NOT override-equivalent, but DO cause a compile time error for other reasons (Name clash - a specific compile time error specified in JLS 8.4.8.3) and therefore do not overload.
Preamble
As I understand it, you're raising a question about the exact semantics of this sentence clause:
"...or the signature of m1 is the same as the erasure of the signature of m2"
In combination with
m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.
Your book implies that this should be interpreted as
"or the erasure of the signature of m1 is the same as the erasure of the signature of m2"
(added words in bold italic).
Whereas you would interpret it as
"or the signature of m1 (without erasure) is the same as the erasure of the signature of m2"
Your interpretation is correct. I don't think the sentence is ambiguous, therefore I think that interpreting it in the first way (i.e. that the erasure of both signatures is the same) is incorrect. You might like to look at this related answer to add weight to my opinion here (I found it as I wanted to check my understanding too).
Answer (however...)
The section of the book you're quoting is actually trying to describe overloading.
Now - when thinking about overloading - the JLS (8.4.9) says that:
If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but signatures that are not override-equivalent, then the method name is said to be overloaded.
This has been consistent since at least Java 6. This is where the link between
override-equivalent
and overloading stems from.OK - so your methods would overload because they are not strictly override-equivalent. Right?
Wrong.
Because just above that section in 8.4.8.3, the JLS puts in a specific compile time error:
It is a compile-time error if a type declaration T has a member method m1 and there exists a method m2 declared in T or a supertype of T such that all of the following are true:
m1 and m2 have the same name.
m2 is accessible from T.
The signature of m1 is not a subsignature (§8.4.2) of the signature of m2.
The signature of m1 or some method m1 overrides (directly or indirectly) has the same erasure as the signature of m2 or some method m2 overrides (directly or indirectly).
This is the scenario in your example. Just below that section, it clarifies why it is necessary:
These restrictions are necessary because generics are implemented via erasure. The rule above implies that methods declared in the same class with the same name must have different erasures. It also implies that a type declaration cannot implement or extend two distinct invocations of the same generic interface.
Side note
The example in the book is a strange one, because Java would not allow overriding of static methods (rather the signature of a method in a subclass could hide that in the superclass). This makes the concept of not being override-equivalent a bit tricky for a learner in my view. However, you can remove the
static
and still see the effect they are trying to demonstrate.这篇关于两个擦除方法相同的擦除方法不需要重写等价(或者它们的签名不是它们之间的子签名)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!