I'm having a hard time trying to understand how inheritance works when it comes to nested classes, I've read a couple of good questions here on SO, but there's something I don't get yet.
To be more specific, I would expect this example
public class Main {
public static void main(String[] args) {
new O().new J();
}
}
class O{
O(){System.out.println("O");}
class I extends O{I(){System.out.println("I");}}
class J extends I{J(){System.out.println("J");}} //compile time error here
}
to run and print OOIJ
, while I get this compile time error on class J
definition: No enclosing instance of type O is available due to some intermediate constructor invocation
.
I understand that this is somehow due to the fact that nested class J
needs an instance of O
to exist before it being initialized, but I think I'm missing some detail about the instantiation chain that takes place when I try to create a J
object.
Why is that happening? Why does changing I
's definition to
class I {I(){System.out.print("I");}}
avoid any compile time error and print OIJ
as I would expect?
EDIT:
I think that this thread only answers my first question:
Why is that happening?
Because J's superclass is itself an inner class I, thus making J's default constructor illegal since it requires an enclosing instance to be supplied to the constructor.
But the second question remain unanswered to me:
Why does changing
I
's definition toclass I {I(){System.out.print("I");}}
avoid any compile time error and print
OIJ
as I would expect?
Shouldn't the problem be still there? J
's superclass is still a inner class, so why is it compiling now?
Notes
Furthermore_1, if I declare I
and J
method-local
public class Main {
public static void main(String[] args) {
new O().foo();
}
}
class O{
O(){System.out.print("O");}
void foo(){
class I extends O{I(){System.out.print("I");}}
class J extends I{J(){System.out.print("J");}}
new J();
}
}
nothing bad happens and it prints OOIJ
, as expected.
Furthermore_2, if I declare I
and J
static
public class Main {
public static void main(String[] args) {
new O.J();
}
}
class O{
O(){System.out.print("O");}
static class I extends O{I(){System.out.print("I");}}
static class J extends I{J(){System.out.print("J");}}
}
I get OIJ
, as expected.