Nested classes

Nested classes are used for

  • logically grouping classes that are only used in one place
  • increasing encapsulation
  • to keep code readable and maintainable

static nested class

The static nested class behave like other top-level class. But it can access to private member of the outer class instance.

public class Demo {
    private int field1;
    private Demo() {}

    public static class DemoBuilder{
        // outer class instance
        private Demo demo = new Demo();

        public DemoBuilder setField1(int v) {
            demo.field1 = v;
            return this;
} } }
Demo.Builder builder = new Demo.Builder(); builder.setField(22); // you can make import as for top-level class import xxx.xxx.Demo.Builder; ... Builder builder = new Builder(); builder.setField(22);

static nested class

The non-static nested classes are called inner classes. Anonymous and local classes are special kinds of inner classes.

Inner class can't declare the static members.

Instance of the inner class can be created only from instance of outer class. Instance of the inner class has hidden reference to outer object that allows to have access to the outer object members directly.

Members of the inner object shadow members of the outer class with same name. The OuterClassName.this construction may resolve this problem.

public class Outer {

    private int field1 = 20;
    private int shadowed = 40;
    private Inner inner = new Inner();

    public void exeInnerMethod() {
        inner.method1();
    }

    class Inner {
        int shadowed = -40;

        public void method1() {
            System.out.println(field1); // 20
            System.out.println(shadowed); // -40
            System.out.println(Outer.this.shadowed); // 40
        }
    }
}
new Outer().exeInnerMethod();

anonymous classes

Anonymous classes enable you to declare and instantiate a class at the same time. They are useful when you need a small implementation of an interface or abstract class in place.

Implementation of interfaces with one abstract method may be replaced by lambdas.

Actually anonymous means that Java compiler will generate name.

public class Demo {
    interface MyStringFactory {
        String newString(int seed);
    }

    // with anonymous class
    MyStringFactory factory1 = new MyStringFactory() {

        @Override
        public String newString(int seed) {
            return "("+seed+")";
        }
    };

    // with lambda syntax    
    MyStringFactory factory2 = seed -> "("+seed+")";
}

local classes

Local classes are defined in a block, typically in the body of a method.