Search code examples
javanested-class

How do I access the instance of an enclosing class?


My question, in abstract terms, is:

How can a non-static inner class access the instance of the enclosing class? This is required for purposes of using the instance as a parameter in method calls and accessing methods and variables with identical names between the inner and enclosing class.

Like the keywords this and super allow you to access specific versions of methods and variables with identical names in the class and the parent, are there keywords to access versions of methods and variables in enclosing classes and enclosed classes?

If you are confused, continue reading:

Consider the following code example, with two classes and an inner class. Main and Outer are two classes in the package "myPackage" (on a side note, I could not get the following code to work without a package/in the default package, for unknown reasons). Inner is an inner, non-static class of Outer.

package myPackage;

public class Outer {
    public void activate() {
        System.out.println("Outer.activate");
    }
    
    public class Inner {
        public void go() {
            activate();
        }
    }
}

package myPackage;

import myPackage.Outer.Inner;

public class Main {

    public static void main(String[] args) {
        Outer myOuter = new Outer();
        Inner myInner = myOuter.new Inner();
        myInner.go();
    }
}

Note that I construct an Inner with myOuter.new Inner(). Since Inner is non-static, it has to be constructed on top of an existing instance of its enclosing class: in this case, myOuter. Therefore, when I call myInner.go(), myInner calls activate(), which calls activate() on its linked instance of the enclosing class. So myInner calls myOuter.activate(), and the output is:

Outer.activate


Now, consider the following changes:

package myPackage;

public class Outer {
    public void activate() {
        System.out.println("Outer.activate");
    }
    
    public class Inner {
        public void activate() {
            System.out.println("Inner.activate");
            activate();
        }
    }
}

package myPackage;

import myPackage.Outer.Inner;

public class Main {

    public static void main(String[] args) {
        Outer myOuter = new Outer();
        Inner myInner = myOuter.new Inner();
        myInner.activate();
    }
}

Now when I call myInner.activate(), myInner outputs, then calls activate(). However, since Inner now has a method called activate(), myInner uses that version instead of the version in the instance of the enclosing class. So myInner calls myInner.activate(), and the output is:

Inner.activate

Inner.activate

Inner.activate

Inner.activate

Inner.activate

Inner.activate

...

Over and over, and ends in a stack overflow error. So my question in this context is how to change Inner.activate() such that it outputs, then calls its enclosing instance version's of activate() instead of its own. The output would then be:

Inner.activate

Outer.activate

Thanks in advance for your assistance.


Solution

  • You access this of the outer class by pre-pending the name of the class to this keyword, as follows:

    Outer.this.activate();
    

    This resolves the scope of this to reference the object of the outer class, which is implicitly stored inside objects of non-static inner classes.

    Demo.