Java Class Hierarchy

I use a hierarchy of inner classes to represent some data in an application, and I came across an error message that I just don't understand. My code can be reduced to the following minimal example:

public class A { public class B extends A {} public class C extends B {} } 

Javac (and my IDE, of course) will not compile the code with the following error message:

 A.java:3: cannot reference this before supertype constructor has been called public class C extends B {} ^ 1 error 

I have not written this anywhere. There is no more code than above, so I assume javac has created something related to the inner class.

I found another way to present my data, so I'm just interested in a good explanation of why it does not compile.

+7
source share
3 answers

You need an instance of an external class to create an internal instance of the class, for example, new Outer().new Inner();

To extend an inner class (parent inner class) with another inner class (child inner class), you cannot call the constructor of the parent inner class because there is no instance of an β€œouter class”.

Try it,

 public class A{ public class B extends A { B() { } } public class C extends B { C() { new A().super(); } } public static void main(String args[]) { } } 

A similar question: An odd situation for "cannot refer to this before the supertype constructor has been called"

+8
source

Another poster is correct, but how to fix it? Just make your class static :

 public class A { public static class B extends A {} public static class C extends B {} } 

Please note that if your inner classes belong to the fields of the outer class, you cannot make them static, otherwise you can (and should - this reduces the dependencies).

+2
source

Your code compiles in Java 7.

The following compiler compiles for Java 6.

  public class C extends B { public C() { A.this.super(); } } 

@saugok a link to a previous question cites Joshua's explanation. Basically, he argued that since C is a subclass of A, C inherits the members of A as members of C. Therefore, B is also a member of C. (For example, let's say the class is the literal CBclass .) So he claims that C.this is an encompassing instance for B super() , so C(){super();} is actually C(){C.this.super();} . Because C.this cannot be evaluated before the super C.this , this is a mistake.

However, this is not like the language specification. See # 8.1.3. Since B not lexically enclosed in C , B not a direct inner class of C , there is no reason to say that an immediate instance of B must be an instance of C

We need to pass B() instance of A It is true that C.this is an instance of A (try this code: new C().new B().new C().new B(); ) so it can be a candidate. There is another candidate, A.this . A.this is accessible and ready to use (it passed as a hidden parameter to C() ).

According to javap , javac 7 compiles the code in

 class B private A this$0; B( A a ) this$0 = a; super(); // A() class C extends B private A this$0; C( A a ) this$0 = a; super( a ); // B(A) 
+1
source

All Articles