-
Sub-task
-
Resolution: Delivered
-
P4
-
23
-
generic
-
generic
Local classes declared inside superclass constructor invocation parameter expressions are no longer compiled with immediately enclosing outer instances.
According to JLS 21 §15.9.2, local and anonymous classes declared in a static context do not have immediately enclosing outer instances. This includes classes declared inside a parameter expression of a `super()` or `this()` invocation in a constructor for some class `C`. Previously, the compiler was incorrectly allowing local classes declared within such parameter expressions to contain references to the `C` outer instance; this is no longer allowed. Although previously allowed, such references were pointless because any subsequent attempt to instantiate the class would trigger a `cannot reference this before supertype constructor has been called` error. Note that the compiler was already correctly disallowing anonymous classes from containing such references.
Although declaring an anonymous inner class within a `super()` or `this()` parameter expression is easy and common, for example in an expression like `super(new Runnable() { ... })`, declaring a local class within a `super()` or `this()` parameter expression is much less common as it requires more syntactic gymnastics. Here's an example that compiled previously but no longer compiles after this change:
```
import java.util.concurrent.atomic.*;
public class Example extends AtomicReference<Object> {
public Example() {
super(switch (0) {
default -> {
class Local {
{ System.out.println(Example.this); }
}
yield null;
// yield new Local(); // generates compiler error
}
});
}
}
```
After this change, the reference to `Example.this` generates a `no enclosing instance of type Example is in scope` compiler error.
According to JLS 21 §15.9.2, local and anonymous classes declared in a static context do not have immediately enclosing outer instances. This includes classes declared inside a parameter expression of a `super()` or `this()` invocation in a constructor for some class `C`. Previously, the compiler was incorrectly allowing local classes declared within such parameter expressions to contain references to the `C` outer instance; this is no longer allowed. Although previously allowed, such references were pointless because any subsequent attempt to instantiate the class would trigger a `cannot reference this before supertype constructor has been called` error. Note that the compiler was already correctly disallowing anonymous classes from containing such references.
Although declaring an anonymous inner class within a `super()` or `this()` parameter expression is easy and common, for example in an expression like `super(new Runnable() { ... })`, declaring a local class within a `super()` or `this()` parameter expression is much less common as it requires more syntactic gymnastics. Here's an example that compiled previously but no longer compiles after this change:
```
import java.util.concurrent.atomic.*;
public class Example extends AtomicReference<Object> {
public Example() {
super(switch (0) {
default -> {
class Local {
{ System.out.println(Example.this); }
}
yield null;
// yield new Local(); // generates compiler error
}
});
}
}
```
After this change, the reference to `Example.this` generates a `no enclosing instance of type Example is in scope` compiler error.
- relates to
-
JDK-8328649 Disallow enclosing instances for local classes in constructor prologues
- Resolved