4

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 to

    class 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.

Community
  • 1
  • 1
Luigi Cortese
  • 10,841
  • 6
  • 37
  • 48
  • see http://stackoverflow.com/questions/8177725/no-enclosing-instance-of-type-perfhelper-is-available-due-to-some-intermediate-c – fantaghirocco Aug 27 '15 at 13:20
  • already done, but "[inner] can only exist when an instance of outer exists" is not a satisfying answer to my curiosity – Luigi Cortese Aug 27 '15 at 13:23
  • Actually I tried to copy and run your first example and it printed out "OOIJ" (each character on new line of course), I did not have compile or runtime errors... – libik Aug 27 '15 at 13:23
  • What version of java are you using? – Nitram Aug 27 '15 at 13:24
  • @libik I'm working on Java 8 – Luigi Cortese Aug 27 '15 at 13:24
  • Yes, I am using Java 1.8 – libik Aug 27 '15 at 13:25
  • 1
    Something strange is happening here... – Luigi Cortese Aug 27 '15 at 13:25
  • Maybe your IDE is not working correctly and think it is uncompilable while it is... What do you use? I tried it on netbeans 8.0.2 – libik Aug 27 '15 at 13:27
  • @SotiriosDelimanolis take a look at my edit. What do you think? – Luigi Cortese Aug 27 '15 at 13:53
  • You second question is solved because the error included `due to some intermediate constructor invocation`. There are no more intermediate constructors. It is invoking `I()` and that by itself is a class with no superclass to address. – Arijoon Aug 27 '15 at 13:58
  • @Arijoon that's not really clear to me, to be honest... Why don't you post an answer that we can discuss further? – Luigi Cortese Aug 27 '15 at 14:04
  • I was going to but the question has been marked duplicated so can't post anything unfortunately. – Arijoon Aug 27 '15 at 17:06
  • I was meant to say `I`'s constructor was the intermediate constructor between `O` and `J`. If `I` doesn't inherit from `O` it's no longer the intermediate and is the superclass itself – Arijoon Aug 27 '15 at 17:07
  • Ok, that's the intuitive answer, but WHY is that a problem? The error message is clear, but what's happening behind the scenes? Why is it a problem having an intermediate constructor? Anyway, I'll probably post another question about this and I'll link it here – Luigi Cortese Aug 27 '15 at 18:37

0 Answers0