Java Inner Class

An Inner Class in Java is a class that is defined within another class. It is a member of the outer class and can access the members (fields and methods) of the outer class, including private members. Inner classes are used to logically group classes that are only used in one place or to increase the encapsulation of your code.

Java supports four types of inner classes

  1. Non-static Nested Class (Inner Class)
  2. Static Nested Class
  3. Local Class
  4. Anonymous Class

Non-static Inner Class

A non-static inner class is associated with an instance of the outer class and can access all the fields and methods of the outer class, including private ones.

Example:


//Main.java file
class OuterClass {
    private String name = "John";

    // Non-static inner class
    class InnerClass {
        void displayName() {
            // Accessing outer class variable
            System.out.println(name);
        }
    }

    void createInnerInstance() {
        InnerClass inner = new InnerClass(); // Creating an inner class object
        inner.displayName();  // Calling method of inner class
    }
}

public class Main {
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.createInnerInstance();
    }
}

Output:

John

Explanation:

  1. OuterClass has a private field name.
  2. The InnerClass is defined within OuterClass. It has access to the private field name from the outer class.
  3. You need an instance of the outer class to create an instance of the inner class, as inner classes are associated with outer class instances.

Static Nested Class

A static nested class is a nested class that is declared static. It can access only the static members of the outer class.

Example:


//Main.java file
class OuterClass {
    private static String name = "John";

    // Static nested class
    static class StaticNestedClass {
        void displayName() {
            // Accessing static outer class member
            System.out.println("My name is: "+name);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // You can directly create an instance of StaticNestedClass without an OuterClass instance
        OuterClass.StaticNestedClass nested = new OuterClass.StaticNestedClass();
        nested.displayName();
    }
}

Output:

My name is: John

Explanation:

  1. The StaticNestedClass can access only the static fields of the outer class, such as name.
  2. It does not require an instance of the outer class to be created.

Local Class

A local class is a class defined within a method, constructor, or block. It can access the local variables and parameters of the method (but only if they are final or effectively final).

Example:


//Main.java file
class OuterClass {
    void outerMethod() {
        final String localVariable = "I am a local variable";
        
        // Local class inside the method
        class LocalClass {
            void display() {
                System.out.println(localVariable);
            }
        }

        // Create an instance of LocalClass and call its method
        LocalClass local = new LocalClass();
        local.display();
    }
}

public class Main {
    public static void main(String[] args) {
        OuterClass outer = new OuterClass();
        outer.outerMethod();
    }
}

Output:

I am a local variable

Explanation:

  1. LocalClass is defined inside the method outerMethod.
  2. It can access the local variables of outerMethod, but the variables must be final or effectively final to be accessed inside the local class.

Anonymous Class

An anonymous class is a class with no name and is used to instantiate objects of a class at the time of creation. It is often used when you want to implement an interface or extend a class without explicitly defining a new class.

Example:


//Main.java file
interface Animal {
    void makeSound();
}

public class Main {
    public static void main(String[] args) {
        // Anonymous class implementing the Animal interface
        Animal animal = new Animal() {
            public void makeSound() {
                System.out.println("Animal make sound.");
            }
        };
        
        animal.makeSound();
    }
}

Output:

Animal make sound.

Explanation:

  1. The anonymous class is created by instantiating the Animal interface and providing the implementation for the makeSound() method directly.
  2. There is no need to define a separate class with a name, which makes this approach compact and useful for short-term tasks.

Benefits of Using Inner Classes

  • Encapsulation: Inner classes allow better encapsulation by keeping classes together that are logically related.
  • Access to Outer Class Members: Inner classes can access all members (including private ones) of the outer class.
  • Improved Code Organization: By grouping related classes together, inner classes help improve code organization, especially when an inner class is used only in one place.