Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is 'T.super' a legal expression as per JLS?

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:

Is T.super a legal expression as per JLS?


Edit: Simplified the code by removing a wrapping inner class.
like image 634
charlie Avatar asked Jan 07 '16 17:01

charlie


2 Answers

No, it's not. Refer to Chapter 19. Searching for the keyword super yields the following constructs:

  • wildcard bounds: extends T / super T;
  • explicit constructor invocation: super(args);
  • field access: [Typename.]super.field;
  • method invocation: [Typename.]super.method();
  • method reference: 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.

like image 178
Sergei Tachenov Avatar answered Sep 30 '22 08:09

Sergei Tachenov


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
like image 24
Clashsoft Avatar answered Sep 30 '22 07:09

Clashsoft