Dmitry Pekach
Dmitry Pekach

Reputation: 161

Use super() with reference in Java

I have three classes

class WithInner {
   class Inner {}
}

public class InheritInner extends WithInner.Inner
{ //constructor
InheritInner(WithInner wi) {
    wi.super();
}
}

This example is taken from Eckel's Thinking in Java. I can't understand why we can't call wi = new WithInner(); instead of .super()? And while calling wi.super() we are calling Object's default constructor, aren't we?

Upvotes: 13

Views: 460

Answers (1)

davmac
davmac

Reputation: 20631

Inner classes maintain a reference to an outer instance (the exception is static inner classes). In this case, a WithInner.Inner instance has a reference to the containing WithInner instance. This association is created when the inner class is instantiated.

You cannot create an instance of the inner class without a reference to the outer class. A class that extends such an inner class also has by implication such a reference, and needs to delegate to the inner class constructor in order to set up the association. The syntax for doing that is as shown in your example:

wi.super();

Here, super() essentially refers to the superclass constructor - that is, the WithInner.Inner constructor. The constructor takes no parameters formally, but it still needs a reference to the outer instance (of type WithInner). The line as a whole essentially means "call the superclass constructor, and associate with the wi instance".

Compare to the syntax for instantiation of an inner class with explicit association:

wi.new WithInner.Inner()

Yes, that's also valid syntax. It's not commonly seen in the wild, though (because inner class instances are normally only created from within the outer class anyway, and in that case the association is implicit - there's no need in that case for this syntax, which provides the association explicitly).

With specific reference to your question:

I can't understand why we can't call wi = new WithInner(); instead of .super()?

This would not associate the created WithInner instance with the inner class instance. You'd get a compile-time error because your InheritInner constructor wouldn't any longer be explicitly calling the synthesized superclass constructor, and it can't be called implicitly because it needs the outer instance reference for association. It's probably easiest to think of the outer instance reference as a hidden parameter to the inner class constructor (indeed, that's how it's implemented under the hood).

And while calling wi.super() we are calling Object's default constructor, aren't we?

No, you're calling the WithInner.Inner constructor, which has a "hidden" parameter for the outer instance reference; wi is essentially passed to the WithInner.Inner constructor as a hidden parameter value.

Upvotes: 8

Related Questions