[type-annos-observers] Clarifying the receiver parameter (qualified 'this')
Markus Keller
markus_keller at ch.ibm.com
Thu Oct 24 05:56:15 PDT 2013
Michael Ernst <mernst at cs.washington.edu> wrote on 2013-10-23 23:34:10:
> First, the change from
> [Identifier .] this
> to
> {Identifier .} this
> was essential. The reason is that inside a doubly-nested inner class,
the
> receiver can have a name like Outer.Middle.this.
Nope, Middle.this is always equivalent to Outer.Middle.this, so the
"Outer." is never necessary.
Example:
package p;
class Outer {
class Middle {
void m() {}
class Inner {
@I Inner(pack. at O Outer. at M Middle Middle.this, Middle m) {
m.m();
Middle.this.m();
}
}
}
}
class Middle { // nasty, but legal
void foo() {}
}
The annotations are on the receiver parameter's type, not on its name, so
the 'this' doesn't have to be qualified with more than the immediately
enclosing class. By the scoping rules, the name of an enclosing member
type can always be referenced with a simple name.
I don't buy the argument that allowing a fully-qualified 'this' makes the
spec simpler. On the contrary: The "8.4.1 Formal Parameters" section in
308.pdf is full of little errors:
"The receiver parameter of an instance method or inner class constructor
is an optional syntactic device to represent the object for which the
method or constructor is invoked."
=> For inner class constructors, the receiver parameter represents the
immediately enclosing instance of the constructed object, not the object
for which the constructor is invoked.
"The name of the receiver parameter must either be 'this', or the text of
a qualified 'this' expression (15.8.3) which would, if present in the body
of the method or constructor, denote the class of the method or
constructor's receiver; otherwise, a compile-time error occurs."
=> The "either ... or" doesn't make it clear that an unqualified 'this'
cannot be used as the receiver parameter of an inner class constructor.
"The type of the receiver parameter must be the class or interface in
which the method or constructor is declared; otherwise, a compile-time
error occurs."
=> For an inner class constructor, the type of the receiver parameter is
_not_ the declaring type of the constructor (which would be the inner
class), but it's the immediately enclosing class of the inner class.
The Java language should stay as simple as possible. Here, the
unrestricted qualifications even confused the spec authors. The
straightforward approach with two separate cases for instance methods and
for inner class constructors is much easier to handle. Why add code to
check whether a qualified 'this' is legal when you can just exclude it in
the grammar? The fully-qualified 'this' adds more complexity to the
language, not less.
Alex Buckley <alex.buckley at oracle.com> wrote on 2013-10-23 20:27:25:
> The receiver parameter is _not_ "closer to being a declaration",
The receiver parameter indeed doesn't declare a variable, but it's an
explicit declaration for the otherwise implicitly declared "this" or
"Outer.this" object. The declaration declares the annotated type of the
'this' object. Another similar example is a public no-args constructor
declaration, which makes the implicit default constructor explicit.
References can use a fully-qualified type name, but the declaration just
uses the simple name.
Markus
More information about the type-annotations-spec-observers
mailing list