Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need to provide enclosing class object but not enclosed class object

class OuterA {
    class InnerA {
    }
}
class SubclassC extends OuterA.InnerA { 
    SubclassC(OuterA outerRef) {
        outerRef.super(); 
    }
}
class XYZ {
    public static void main(String[] args) {
        new SubclassC(new OuterA());
    }
}

In the above code

  1. Why do I need to pass OuterA object reference to SubclassC constructor for the .java file to compile?
  2. Why is InnerA object reference not required to be passed to SubclassC constructor?
like image 629
paidedly Avatar asked Mar 26 '15 19:03

paidedly


2 Answers

Why do I need to pass OuterA object reference to SubclassC constructor for the .java file to compile?

Because SubclassC extends the definition of the InnerA class. Meanwhile, InnerA class is bound to OuterA (i.e. all the instances of InnerA will be bound to a corresponding instance of OuterA). Therefore, to obtain an instance of SubclassC, you need an instance of OuterA.

Why is InnerA object reference not required to be passed to SubclassC constructor?

Because when creating a SubclassC, under the hood, an instance of its superclass will be created first, i.e there will be a instance of InnerA. You can actually look on SubclassC as a special kind of InnerA.

like image 54
Konstantin Yovkov Avatar answered Oct 16 '22 20:10

Konstantin Yovkov


  1. Why do I need to pass OuterA object reference to SubclassC constructor for the .java file to compile?

Because InnerA is an inner class of OuterA. This means that an object of type OuterA.InnerA or any of its subtypes, such as SubclassC, can only exist in the context of an enclosing class (OuterA in this case) instance.

This is called a Qualified superclass constructor invocation. From the JLS:

Qualified superclass constructor invocations begin with a Primary expression . They allow a subclass constructor to explicitly specify the newly created object's immediately enclosing instance with respect to the direct superclass (§8.1.3). This may be necessary when the superclass is an inner class.

If you don't need to link the SubclassC instance to an already existing instance of OuterA, you can create the new OuterA object in the SuperclassC constructor:

static class SubclassC extends OuterA.InnerA {
    SubclassC() {
        new OuterA().super();
    }
}
  1. Why is InnerA object reference not required to be passed to SubclassC constructor?

Since SubclassC extends OuterA.InnerA, when you do outerRef.super() you are calling the OuterA.InnerA constructor. To see that this is the case, consider the code below:

public class Example {
    static class OuterA {
        OuterA() {
            System.out.println("Call OuterA constructor");
        }
        class InnerA {
            InnerA() {
                System.out.println("Call InnerA constructor");
            }

        }
    }

    static class SubclassC extends OuterA.InnerA {
        SubclassC(OuterA outerRef) {
            outerRef.super();
            System.out.println("Call SuperclassC constructor");
        }
    }

    public static void main(String[] args) {
        OuterA outerA = new OuterA();
        System.out.println("Before new SuperclassC()");
        new SubclassC(outerA);
    }
}

Output:

Call OuterA constructor
Before new SuperclassC()
Call InnerA constructor
Call SuperclassC constructor
like image 43
Anderson Vieira Avatar answered Oct 16 '22 19:10

Anderson Vieira