Consider the following set of expressions:
class T {{
/*1*/ Object o = T.super; // error: '.' expected
/*2*/ o.toString();
}}
An attempt to compile this will fail on line /*1*/
with the error:
error: '.' expected
o = T.super;
^
both when using OpenJDK 1.8.0 (Ubuntu) or Oracle JDK 1.8 (Windows).
However, Eclipse 4.5.0 (Mars) compiles this without any error and it results in:
class T {
T();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8] // super()
4 aload_0 [this]
5 astore_1 [o] // o = T.super
7 invokevirtual java.lang.Object.toString() : java.lang.String [10]
10 pop // ^-- o.toString()
11 return
}
From this you can see that the line /*1*/
of the java code (line 5
of the result) correctly stores this
casted as Object
(Eclipse's understanding of T.super
) into the local variable o
. When the code is executed, it completes normally and the line /*2*/
produces a correct result.
So far I failed to find anything relevant to o = T.super;
in the Java 8 Language Specification, i.e. whether it's legal or not. Since it doesn't explicitly state that it's a legal expression, my guess is that it means it's illegal. But then, why Eclipse considers it legal? Hence my question:
T.super
a legal expression as per JLS?No, it's not. Refer to Chapter 19. Searching for the keyword super
yields the following constructs:
extends T
/ super T
;super(args)
;[Typename.]super.field
;[Typename.]super.method()
;super::method
.The fact that it compiles may be considered a bug or a language extension, although there is no real difference between the two.
T.super
is not a legal expression because it does not make sense. The super
(with or without explicit type) syntax is only used to call methods from the super class. T.super
does not call any method (if it were legal syntax), it only references a class instance. In your case, it references the outer T
instance. The correct syntax would be T.this
, which would point to the outer this
.
Your class definition can be viewed like this (with a named inner class):
class Outer
{
// Constructor Body
{
class Inner
{{
/*1*/ Outer o = Outer.super; // error: '.' expected
/*2*/ o.toString();
}};
new Inner();
}
}
The correct way to reference the outer class would be
Outer o = Outer.this; // valid
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With