Reputation: 27425
I've read about class constructor here and a question then arises as to why does the following hierachy is incorrect:
public class Test extends Subclass.Inner{ //compile-time error
//The hierarchy of the type Test is inconsistent
public Test() {
super();
}
}
public class Subclass extends Test{
public class Inner{
}
}
Formally
If a superclass constructor invocation statement is unqualified, and if S is an inner member class, then it is a compile-time error if S is not a member of a lexically enclosing class of C by declaration or inheritance.
I thought the example completely satisfies the rule I cited. In the case SubClass
is lexically inclosing class for Test
by inheritance. Why doesn't the code work fine? Could you provide an appropriate example reflecting that?
Upvotes: 4
Views: 312
Reputation: 37855
Here is a clause you are missing (8.4.1):
A class C directly depends on a type T if T is mentioned in the
extends
orimplements
clause of C either as a superclass or superinterface, or as a qualifier of a superclass or superinterface name.A class C depends on a reference type T if any of the following conditions hold:
- C directly depends on a class D that depends on T (using this definition recursively).
It is a compile-time error if a class depends on itself.
It is a compile-time error because the declaration of a superclass of Subclass
contains Subclass
as a qualifier of a superclass name.
That is besides the extremely weird circular definition you have going here. Test
would be an outer scope of itself.
This doesn't compile either, though it's not as puzzling as the inner class:
class Test implements Test.ITest {
interface ITest {}
}
Netbeans gives me a more straightforward error that there is 'cyclic inheritance'. A class declaration is not allowed to reference itself in this manner.
Upvotes: 1
Reputation: 54
Inner instance classes (non-static) are actually transformed like so:
public class Subclass extends Test {
public class Inner {
}
}
becomes something like this:
public class Subclass extends Test {
}
public class Inner {
Subclass parent;
public Inner(Subclass parent) {
this.parent = parent;
}
}
The following is valid:
public class Container extends Subclass {
public class Test extends Subclass.Inner {
public Test() {
super();
}
}
}
public class Subclass {
public class Inner {
}
}
Upvotes: 2
Reputation: 393936
An instance of an inner class must have an enclosing instance, which gets initialized before the inner class instance. On the other hand, a super class constructor is always executed before a sub-class constructor. Therefore, creating an instance of SubClass
requires calling first the constructor of Test
, which requires calling first the constructor of SubClass.Inner
, but SubClass.Inner
cannot be initialized before its containing instance.
I believe that in order to satisfy the condition you quoted, the super class Inner must be enclosed by a super class of Test. In your case it is enclosed by a sub-class of Test.
Upvotes: 2