问题
I have a rather technical question concerning the definition of override-equivalent (JLS 8.4.2) in the context of receiver parameters.
Edit: After posting this question, there was a lot of confusion in the comments about receiver parameters. Many people seemed to believe that having a parameter named this
in the code below is illegal and therefore misunderstood the question. Please refer to https://docs.oracle.com/javase/specs/jls/se9/html/jls-8.html#jls-8.4.1 if you do not know this feature. A perhaps more easily understandable explanation can be found here: http://blog.joda.org/2015/12/explicit-receiver-parameters.html. This question is very technical and addresses rather experienced Java developers who are familiar with receiver parameters and know the Java Language Specification (JLS) well.
The term override-equivalent is defined as follows:
The signature of a method
m1
is a subsignature of the signature of a methodm2
if either:
m2
has the same signature asm1
, or- the signature of
m1
is the same as the erasure (§4.6) of the signature ofm2
.Two method signatures
m1
andm2
are override-equivalent iff eitherm1
is a subsignature ofm2
orm2
is a subsignature ofm1
.
Thus, if I understand correctly, the two methods in the following class are not override-equivalent, even though, intuitively, I would have expected them to be:
class A {
void foo(A this) { /* ... */ }
void foo() { /* ... */ }
}
Nevertheless, obviously I cannot declare both methods in the same class, and when I try to do so, the compiler rightfully complains that foo()
is already defined.
My question consists of two parts:
- Do I understand correctly that the above two methods are not override-equivalent?
- If no: What part of the definition did I miss?
- If yes: What rule in the JLS formally forbids the above two method definitions to be simultaneously present in the same class, since in this case it cannot be the rule "It is a compile-time error to declare two methods with override-equivalent signatures in a class." (JLS 8.4.2)
回答1:
Ok, I found out the answer, and I'll just leave it here in the hopes it may someday help someone.
The answer to my two-part question would be:
No, the two methods in the original post are override-equivalent.
The relevant part of the definition is the first sentence of JLS 8.4.2:
Two methods or constructors,
M
andN
, 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 ofN
to the the type parameters ofM
, the same formal parameter types.
I had read that part, but I assumed that a receiver parameter, while special, is also to be considered as (a special kind of) formal parameter. Thus I assumed that receiver parameters were implicitly included in the sentence "(...) after adapting the formal parameter types (...)" (emphasis mine). However, that is not the case. Receiver parameters are not also formal parameters; rather, the definitions of receiver parameter and formal parameter are mutually exclusive. Therefore, receiver parameters are not part of a method signature as defined in the above quote. Since the definition of override-equivalent uses the definition of a method signature, this also means that the two methods in my original post are in fact override-equivalent (because they do have the same signature!).
The relevant section that clarifies that receiver parameters are indeed not also formal parameters comes slightly later in section JLS 8.4.2:
The receiver parameter is an optional syntactic device for an instance method or an inner class's constructor. For an instance method, the receiver parameter represents the object for which the method is invoked. For an inner class's constructor, the receiver parameter represents the immediately enclosing instance of the newly constructed object. Either way, the receiver parameter exists solely to allow the type of the represented object to be denoted in source code, so that the type may be annotated. The receiver parameter is not a formal parameter; more precisely, it is not a declaration of any kind of variable (§4.12.3), it is never bound to any value passed as an argument in a method invocation expression or qualified class instance creation expression, and it has no effect whatsoever at run time.
(emphasis mine)
The statement that the receiver parameter is not a formal parameter got a bit lost in that big blob of text there.
来源:https://stackoverflow.com/questions/49533897/is-a-method-with-receiver-parameter-override-equivalent-to-the-same-method-decla