Anonymous Inner Classes and non-static inner class


Anonymous Inner Classes

An anonymous inner class is a form of inner class that is declared and instantiated with a single statement. As a consequence, there is no name for the class that can be used elsewhere in the program; i.e. it is anonymous.

Anonymous classes are typically used in situations where you need to be able to create a light-weight class to be passed as a parameter. This is typically done with an interface. For example:

public static Comparator<String> CASE_INSENSITIVE =
	new Comparator<String>() {
		@Override
		public int compare(String string1, String string2) {
			return string1.toUpperCase().compareTo(string2.toUpperCase());
		}
	};

This anonymous class defines a Comparator<String> object (CASE_INSENSITIVE) that compares two strings ignoring differences in case.

Other interfaces that are frequently implemented and instantiated using anonymous classes are Runnable and Callable. For example:

// An anonymous Runnable class is used to provide an instance that the Thread
// will run when started.
Thread t = new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("Hello world");
	}
});
t.start(); // Prints "Hello world"

Anonymous inner classes can also be based on classes. In this case, the anonymous class implicitly extends the existing class. If the class being extended is abstract, then the anonymous class must implement all abstract methods. It may also override non-abstract methods.

Constructors

An anonymous class cannot have an explicit constructor. Instead, an implicit constructor is defined that uses super(...) to pass any parameters to a constructor in the class that is being extended. For example:

SomeClass anon = new SomeClass(1, "happiness") {
	@Override
	public int someMethod(int arg) {
		// do something
	}
    };

The implicit constructor for our anonymous subclass of SomeClass will call a constructor of SomeClass that matches the call signature SomeClass(int, String). If no constructor is available, you will get a compilation error. Any exceptions that are thrown by the matched constructor are also thrown by the implicit constructor.

Naturally, this does not work when extending an interface. When you create an anonymous class from an interface, the classes superclass is java.lang.Object which only has a no-args constructor.


Create instance of non-static inner class from outside

An inner class which is visible to any outside class can be created from this class as well.

The inner class depends on the outside class and requires a reference to an instance of it. To create an instance of the inner class, the new operator only needs to be called on an instance of the outer class.

class OuterClass {
	class InnerClass {
	}
}
 
class OutsideClass {
 
	OuterClass outer = new OuterClass();
 
	OuterClass.InnerClass createInner() {
		return outer.new InnerClass();
	}
}

Method Local Inner Classes

A class written within a method called method local inner class. In that case the scope of the inner class is restricted within the method.

A method-local inner class can be instantiated only within the method where the inner class is defined.

The example of using method local inner class:

public class MyClass {
    private void myMethod() {
        final int myInt = 42;
 
        // Method Local Inner Class
        class LocalInnerClass {
            private void display() {
                System.out.println("Local inner class with value: " + myInt);
            }
        }
 
        // Accessing the inner class
        LocalInnerClass inner = new LocalInnerClass();
        inner.display();
    }
 
    public static void main(String args[]) {
        MyClass myClass = new MyClass();
        myClass.myMethod();
    }
}

Executing will give an output:

Local inner class with value: 42

Accessing the outer class from a non-static inner class

The reference to the outer class uses the class name and this

public class OuterClass {
	public class InnerClass {
		public void method() {
			System.out.println("I can access my enclosing class: " + OuterClass.this);
		}
	}
}

You can access fields and methods of the outer class directly.

public class OuterClass {
	private int counter;
 
	public class InnerClass {
		public void method() {
			System.out.println("I can access " + counter);
		}
	}
}

But in case of name collision you can use the outer class reference.

public class OuterClass {
	private int counter;
	public class InnerClass {
		private int counter;
 
		public void method() {
			System.out.println("My counter: " + counter);
			System.out.println("Outer counter: " + OuterClass.this.counter);
 
			// updating my counter
			counter = OuterClass.this.counter;
		}
	}
}

Basic Programs