Contents | Prev | Next Inner Classes Specification


How do inner classes affect the idea of this in Java code?

Recall that the code of a top-level class T can make use of the current instance, either directly by means of the keyword this, or indirectly, by naming one of the instance members of T. The idea of a current instance has been extended, so that inner classes have more than one current instance. This allows the code of an inner class C to execute relative to an enclosing instance of its outer class, as well as the current instance of C.

In our first example of adapter classes, the Enumerator code had two current instances, the enclosing FixedStack and the Enumerator object itself. More generally, within the entire body of an inner class C, there is a current instance for C, another current instance for every inner class enclosing C, and finally a current instance for the innermost enclosing top-level class. (A static class is a top-level class, not an inner class. Therefore, our enumeration of current instances stops at the first static keyword.)

Top-level classes do not have multiple current instances. Within the non- static code of a top-level class T, there is one current instance of type T. Within the static code of a top-level class T, there are no current instances. This has always been true of top-level classes which are package members, and is also true of top-level classes which are static members of other top-level classes. It is as if all package members have been implicitly static all along.

In all classes, each current instance can be named explicitly or can play an implicit part when its members are used. Any current instance can be referred to by explicitly qualifying the keyword this as if it were a name: FixedStack.this, Enumerator.this, etc. (This notation is always effective, since the language prohibits an inner class from having the same name as any of its enclosing classes.) As always, the innermost current instance can be named with the unqualified keyword this.

Remember that an instance variable reference m has the same meaning as a field reference expression this.m, so the current instance is implicitly used. In a given piece of code, all members of all current classes are in scope and usable (except for name hiding by intervening scopes). The simple name of a member is implicitly qualified by the current instance in whose class the name was found. (All static members of enclosing classes are always usable.)

In particular, Java code can directly use all methods of all current instances. Class scoping does not influence overloading: If the inner class has one print method, the simple method name print refers to that method, not any of the ten print methods in the enclosing class.

Enclosing classes and instantiation

It is sometimes useful to speak of an enclosing instance of an inner class C. This is defined as any current instance within C, other than the instance of C itself. Every instance of C is permanently associated with its enclosing instances.

When a constructor is invoked, the new object must be supplied with an enclosing instance, which will become a current instance for all the code executed by the new object. (If there are layers of enclosing instances, the innermost is required, and it in turn determines all the others.) The enclosing instance may be specified explicitly, by qualifying the keyword new:

    class Automobile {
        class Wheel {
            String hubcapType;
            float radius;
        }
    
        Wheel leftWheel = this. new Wheel();
        Wheel rightWheel = this. new Wheel();
        Wheel extra;
    
        static void thirdWheel(Automobile car) {
            if (car.extra == null) {
                car.extra = car. new Wheel();
            }
            return car.extra;
        }
    }
    
    class WireRimWheel extends Automobile.Wheel {
        WireRimWheel(Automobile car, float wireGauge) {
            car. super();
        }
    }

A subclass of an inner class C must pass an enclosing instance to C's constructor. This may be done, as just shown, by explicitly qualifying the keyword super. By default, a current instance of the caller becomes the enclosing instance of a new inner object. In an earlier example, the expression new Enumerator() is equivalent to the explicitly qualified this.new Enumerator(). This default is almost always correct, but some applications (such as source code generators) may need to override it from time to time.


Contents | Prev | Next

Inner Classes Specification (HTML generated by dkramer on March 15, 1997)
Copyright © 1996, 1997 Sun Microsystems, Inc. All rights reserved
Please send any comments or corrections to john.rose@eng.sun.com