Java Nested Classes

The classes defined within another class are known as nested classes. The scope of a nested class is bounded by the scope of its enclosing class. Thus, if class B is defined within class A, then B does not exist independently of A.

A nested class has access to the members, including private members, of the class in which it is nested. However, the enclosing class does not have access to the members of the nested class.

A nested class that is declared directly within its enclosing class scope is a member of its enclosing class.

 

Types

There are mainly two types of nested classes: static and non-static. Inner class, anonymous class and method local class falls under non-static nested classes.

1. Inner class

An inner class is a non-static nested class. It has access to all of the variables and methods of its outer class and may refer to them directly in the same way that other non-static members of the outer class do.

Inner class can be instantiated within the outer class (but not static), and inner class instantiation code that's outside the outer class:

  • From inside the outer class instance code, use the inner class name in the normal way:
MyInner mi = new MyInner();
  • From outside the outer class instance code (including static method code within the outer class), the inner class name must now include the outer class's name:
MyOuter.MyInner

To instantiate it, you must use a reference to the outer class:

new MyOuter().new MyInner(); or outerObjRef.new MyInner();

if you already have an instance of the outer class.

The following program explains more about inner class.

/**
 * Example of an inner class.
 */
class Outer {
    private int outer_x = 100;

    void display() {
        Inner inner = new Inner();    // make an inner instance inside outer class
        inner.display(10);
    }

    //an inner class
    class Inner {
        void display(int integer) {
            System.out.println("display() in Inner: outer_x = " + outer_x+" arg: "+integer);
        }
    }
}

public class InnerClassApp {
    public static void main(String args[]) {
        Outer outer = new Outer();
        outer.display();    //calls display() of Outer class

        //creating instance of inner class outside outer class
        Outer.Inner inner = outer.new Inner();
        inner.display(20);    //calls display() of Inner class
    }
}

The output of the program is:

display() in Inner: outer_x = 100 arg: 10
display() in Inner: outer_x = 100 arg: 20

Here, method display() inside inner class Inner can access the member, even if it is private, of outer class.

Also, there will be two .class files for class Outer: one is Outer.class and another is Outer$Inner.class . However, the only way you can access the inner class is through a live instance of the outer class! In other words, only at runtime when
there's already an instance of the outer class to tie the inner class instance to.

 

2. Method-Local Inner Classes

An inner class defined within a method in called method-local inner class.

To make compiler be able to find the inner class you must make an instance of it somewhere within the method but below the inner class definition.

The following program explains more about method-local inner class.

/**
 * Method-local inner class example
 */
public class MyOuter {
    private int x = 100;
    void doStuff() {
        class MyInner {
            public void seeOuter() {
                System.out.println("Outer x is " + x);
            } // close inner class method
        } // close inner class definition
        MyInner mi = new MyInner(); // This line must come
                                    // after the class
        mi.seeOuter();
    } // close outer class method doStuff()
} // close outer class
class TestMethodLocal{
    public static void main(String[] args) {
        MyOuter myOuter= new MyOuter();
        myOuter.doStuff();
    }
}

The output of the program is:

Outer x is 100

 

3. Anonymous Inner Classes

Inner classes declared without any class name at all are anonymous classes.

/**
 * Anonymous class
 */
class Coffee {
    public void prepare() {
        System.out.println("Coffee");
    }
}
class Drink {
    Coffee coffee = new Coffee() {
        public void prepare() {
            System.out.println("Anonymous Coffee");
        }
    };   //Do not forget semicolons following curly braces.
}

Here, The Coffee reference variable coffee refers not to an instance of Coffee, but to an instance of an anonymous subclass of Coffee.

Polymorphism is in play when anonymous inner classes are involved.

By adding the following code snippet, our program completes.

public class AnonymousInnerClass{
    public static void main(String[] args) {
        Drink drink = new Drink();
        drink.p.prepare();
    }
}

The output of the program is:

Anonymous Coffee

 

4. Static Nested Classes

A static nested class is one that has the static modifier applied. Because it is static, it must access the members of its enclosing class through an object. That is, it cannot refer to members of its enclosing class directly. Because of this restriction, static nested classes are seldom used.

A static nested class is simply a class that's a static member of the enclosing class:

class BigOuter {
     static class Nested { 
           //...
     }
}

The class itself isn't really "static"; there's no such thing as a static class. The static modifier in this case says that the nested class is a static member of the outer class. That means it can be accessed, as with other static members, without having an instance of the outer class.

The syntax for instantiating a static nested class from a non-enclosing class is:

OutClassName.NestedStaticClassName varName = new OutClassName.NestedStaticClassName();

The following program illustrates more about static nested class.

/**
 * Example of Static Nested Class
 */
public class StaticNestedApp {
    static class Nest {
        void print() {
            System.out.println("Inside Nest.");
        }
    }
    public static void main(String[] args) {
        BigOuter.StaticNested n = new BigOuter.StaticNested(); // both class names
        n.go();
        Nest nest = new Nest(); // access the enclosed class
        nest.print();
    }
}

class BigOuter {
    static class StaticNested {
        void go() {
            System.out.println("Inside StaticNested.");
        }
    }
}

The output of the program is:

Inside StaticNested.
Inside Nest.
Java String Class
Java Inheritance (IS-A)