(I keep re-reading that question title and thinking about how ridiculous it must look, but I assure you that is the best description of the problem, and I have an actual application where this is the best structure. I swear I'm not crazy.)
Consider the following. Each block is a separate file:
package myPackage;
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
}
}
package myPackage;
import myPackage.A.B;
public class Main {
public static void main(String[] args) {
class C extends B {
public C(A enclosingInstance) {
enclosingInstance.super();
}
public void show() {
System.out.println(A.this.i);
}
}
A myA = new A(2);
C myC = new C(myA);
myC.show();
}
}
Note that the enclosingInstance
business is to solve a problem involving intermediate constructor invocations. See "Why can't outer classes extend inner classes?".
I would expect the output to be "2". But instead, I have a compile error on System.out.println(A.this.i);
:
No enclosing instance of the type A is accessible in scope
I think the programmatic concept I'm trying to solve is sound: Create a new type of B inside main
to give to A that uses things from A that types of B can access.
So what am I doing wrong, or why isn't this possible in java?
EDIT/UPDATE: Note that the same error appears when the code in main
is moved to a non-static method. That is to say, I tried moving everything inside of static void main
to a new, non-static method of class Main
called go()
. Then I changed static void main
to the single line new Main().go();
. The error is in the same spot. So it doesn't seem to be an issue of class C
being defined in a static context.
You want A.this
to refer to the enclosing instance of the B
instance. But why should it? That's not what the syntax means. A.this
would mean the enclosing A
instance of the C
instance, and this does not make sense because C
is not an inner class of A
.
To make this clearer, here is an example where C
is an inner class of A
.
public class A {
public int i;
public A(int i) {
this.i = i;
}
public class B {
void foo() {
System.out.println(A.this.i);
}
}
public class C extends B {
C(A a) {
a.super();
}
void bar() {
System.out.println(A.this.i);
}
}
public static void main(String[] args) {
A a1 = new A(1);
A a2 = new A(2);
C c = a1.new C(a2);
c.foo();
c.bar();
}
}
Here C
extends B
, and both C
and B
are inner classes of A
. Therefore any C
has an enclosing A
instance, and it also has an enclosing A
instance when considered as a B
, and these enclosing instances are different (as proved by the fact that foo
and bar
print different numbers).
So, A.this
could not possibly mean what you want it to mean, because it already means something else. I guess the reason why the language designers didn't come up with other syntax to mean the enclosing instance of a super class, is because such syntax would be very complicated, with little pay-off (simple workarounds already exist).