Java Inner Classes..

The Good, the Bad and the Ugly..


What is it that we are trying to solve?

A class must be cohesive, must contain code only related to what it is doing. Sometimes, when designing a class, you realise the code you are adding belongs to a separate class, but highly related to the class you are already designing; Event Handlers are perfect example. What do you do? -> Inner Classes to rescue!

What is an Inner Class?

A member of the Outer Class, just like any other member such as instance fields or methods.

Benefits of Inner Classes?

An Inner Class instance can access all members of the Outer Class, even the private ones!

Show me some code please?

class OuterClass {
    class InnerClass {
    }
}

Anything I need to keep in mind?

  • Inner Classes can not have any static declarations, except constant variable declarations.
  • To create an instance of an Inner Class, you must have an instance of the Outer Class.

In Java pls?

Try compiling App.java..
public class App {
    public static void main(String[] args) {
    }
}
 
class OuterClass {
    class InnerClass {
        static int foo; // will not compile!
    }
}

And you will get..
App.java:9: error: Illegal static declaration in inner class OuterClass.InnerClass
        static int foo; // will not compile!
                   ^
  modifier 'static' is only allowed in constant variable declarations

Make foo a constant variable declaration, and try compiling again..
public class App {
    public static void main(String[] args) {   
    }
}
 
class OuterClass {
    class InnerClass {
        static final int foo = 100; // 
    }
}

And how do I get an instance of the OuterClass?

public class App {
    public static void main(String[] args) {
        // Getting an instance of the Inner Class, from some other Class..
        final OuterClass.InnerClass ic = new OuterClass().new InnerClass();
    }
}
 
class OuterClass {
 
    void foo() {
        // Getting an instance of the Inner Class from the Outer Class.
        final InnerClass ic = new InnerClass();
    }
 
    class InnerClass {
        static final int foo = 100; // 
    }
}

Method-Local Inner Classes 

Some further discussion can be found here. Simply: The Inner Class instance can not access local variables of the method unless they are final! And do not forget: Method-Local Inner Classes can only be marked final or abstract, and obviously not at the same time! Method-Local Inner Classes can not be public, private, protected or static!

Here is a very simple example for you..
public class App {
    public static void main(String[] args) {
        final OuterClass oc = new OuterClass();
        oc.foo();
    }
}
 
class OuterClass {
 
    private int outerFoo = 99;
 
    void foo() {
        int methodFoo = 10; 
        final int methodFinalFoo = 20;
 
        class MethodInnerClass {
            int methodInnerInstanceFoo = 21;
            static final int methodInnerStaticFinalFoo = 42;
            void printAllYouCan() {
                System.out.println("OuterFoo: " + outerFoo);
                System.out.println("MethodFinalFoo: " + methodFinalFoo);
                System.out.println("MethodInnerInstanceFoo: " + methodInnerInstanceFoo);
                System.out.println("methodInnerStaticFinalFoo: " + methodInnerStaticFinalFoo);
            }
        }
 
        final MethodInnerClass mic = new MethodInnerClass();
        mic.printAllYouCan();
    }
}

and the output will be..
MacBook-Pro:Desktop koraytugay$ javac App.java
MacBook-Pro:Desktop koraytugay$ java App
OuterFoo: 99
MethodFinalFoo: 20
MethodInnerInstanceFoo: 21
methodInnerStaticFinalFoo: 42

Anonymous Inner Classes

Explained here!

Static Nested Classes

Does not enjoy the special relationship with the Outer Class like the other Inner Classes. Technically, Static Nested Classes are not even Inner Classes.. A Static Nested class is simply a Class that is a static member of the enclosing class..

An Example Please?

public class App {
    public static void main(String[] args) {
        EnclosingClass.NestedInnerClass en_01 = new EnclosingClass.NestedInnerClass();
        EnclosingClass.NestedInnerClass en_02 = new EnclosingClass.NestedInnerClass();
 
        en_01.incrementCounter();
        en_02.incrementCounter();
 
        System.out.println(EnclosingClass.NestedInnerClass.counter);
    }
}
 
class EnclosingClass {
    static class NestedInnerClass {
        static int counter = 0;
 
        public void incrementCounter() {
            counter++;
        }
    }
}

Output will be..
MacBook-Pro:Desktop koraytugay$ javac App.java
MacBook-Pro:Desktop koraytugay$ java App
2

Notes?

The class itself is not static. It is a static member of the Outer Class, which means it can be accessed without having an instance of the Outer Class. This was not the case with the Inner Classes that were explained before!

Just as a static method does not have access to the instance variables and nonstatic methods of the class, a static nested class does not have access to the instance variables and nonstatic methods of the outer class.

Also note: a static nested class can have static members that need not be final!