Nested Classes in Java

Introduction

Nested classes in Java are classes defined within another class. They are used to logically group classes that are only used in one place, increase encapsulation, and can lead to more readable and maintainable code. Java supports four types of nested classes: static nested classes, non-static nested classes (inner classes), local inner classes, and anonymous inner classes.

Key Points:

  • Encapsulation: Nested classes can access private members of the enclosing class.
  • Logical Grouping: Helps in logically grouping classes that are only used in one place.
  • Types of Nested Classes: Static nested classes, non-static nested classes (inner classes), local inner classes, and anonymous inner classes.

Table of Contents

  1. Static Nested Classes
  2. Non-static Nested Classes (Inner Classes)
  3. Local Inner Classes
  4. Anonymous Inner Classes
  5. Real-World Example
  6. Conclusion

1. Static Nested Classes

A static nested class is a static member of the outer class. It can access static members of the outer class but cannot directly access non-static members.

Example:

public class OuterClass {
    private static String staticOuterField = "Static Outer Field";

    // Static nested class
    public static class StaticNestedClass {
        public void display() {
            System.out.println("Accessing: " + staticOuterField);
        }
    }
}

public class StaticNestedClassExample {
    public static void main(String[] args) {
        OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
        nestedObject.display();  // Outputs: Accessing: Static Outer Field
    }
}

Explanation:

  • OuterClass: The outer class containing a static nested class.
  • StaticNestedClass: The static nested class.
  • StaticNestedClassExample: Demonstrates creating an instance of the static nested class and calling its method.

2. Non-static Nested Classes (Inner Classes)

An inner class is associated with an instance of its enclosing class. It can access both static and non-static members of the outer class.

Example:

public class OuterClass {
    private String outerField = "Outer Field";

    // Inner class
    public class InnerClass {
        public void display() {
            System.out.println("Accessing: " + outerField);
        }
    }
}

public class InnerClassExample {
    public static void main(String[] args) {
        OuterClass outerObject = new OuterClass();
        OuterClass.InnerClass innerObject = outerObject.new InnerClass();
        innerObject.display();  // Outputs: Accessing: Outer Field
    }
}

Explanation:

  • OuterClass: The outer class containing an inner class.
  • InnerClass: The inner class.
  • InnerClassExample: Demonstrates creating an instance of the inner class and calling its method.

3. Local Inner Classes

A local inner class is defined within a block, such as a method or an if statement. It can access final or effectively final variables of the enclosing block.

Example:

public class OuterClass {
    public void display() {
        String localVariable = "Local Variable";

        // Local inner class
        class LocalInnerClass {
            public void show() {
                System.out.println("Accessing: " + localVariable);
            }
        }

        LocalInnerClass localInner = new LocalInnerClass();
        localInner.show();  // Outputs: Accessing: Local Variable
    }
}

public class LocalInnerClassExample {
    public static void main(String[] args) {
        OuterClass outerObject = new OuterClass();
        outerObject.display();
    }
}

Explanation:

  • OuterClass: The outer class containing a method with a local inner class.
  • LocalInnerClass: The local inner class defined within a method.
  • LocalInnerClassExample: Demonstrates calling a method that uses a local inner class.

4. Anonymous Inner Classes

An anonymous inner class is a class without a name and is both declared and instantiated in a single statement. It is typically used to provide a concrete implementation of an interface or abstract class on the fly.

Example:

interface Greeting {
    void sayHello();
}

public class AnonymousInnerClassExample {
    public static void main(String[] args) {
        Greeting greeting = new Greeting() {
            @Override
            public void sayHello() {
                System.out.println("Hello from Anonymous Inner Class");
            }
        };
        greeting.sayHello();  // Outputs: Hello from Anonymous Inner Class
    }
}

Explanation:

  • Greeting: An interface with a single method.
  • AnonymousInnerClassExample: Demonstrates creating an anonymous inner class that implements the Greeting interface.

5. Real-World Example

Let's create a real-world example using different types of nested classes.

Example:

public class Computer {
    private String brand = "Brand Name";

    // Static nested class
    public static class Processor {
        private String model = "Intel i9";

        public String getModel() {
            return model;
        }
    }

    // Inner class
    public class RAM {
        private String size = "16GB";

        public String getSize() {
            return size;
        }

        public String getBrand() {
            return brand;  // Accessing outer class field
        }
    }

    // Method with local inner class
    public void startComputer() {
        String status = "Starting";

        class Power {
            public void turnOn() {
                System.out.println(status);  // Accessing local variable
            }
        }

        Power power = new Power();
        power.turnOn();
    }
}

public class RealWorldExample {
    public static void main(String[] args) {
        // Static nested class usage
        Computer.Processor processor = new Computer.Processor();
        System.out.println("Processor Model: " + processor.getModel());  // Outputs: Processor Model: Intel i9

        // Inner class usage
        Computer computer = new Computer();
        Computer.RAM ram = computer.new RAM();
        System.out.println("RAM Size: " + ram.getSize());  // Outputs: RAM Size: 16GB
        System.out.println("Computer Brand: " + ram.getBrand());  // Outputs: Computer Brand: Brand Name

        // Local inner class usage
        computer.startComputer();  // Outputs: Starting
    }
}

Explanation:

  • Computer: The outer class with a static nested class (Processor), an inner class (RAM), and a method with a local inner class (Power).
  • RealWorldExample: Demonstrates using the static nested class, inner class, and local inner class.

6. Conclusion

Nested classes in Java provide a way to logically group classes that are only used in one place, increase encapsulation, and make the code more readable and maintainable. Understanding the different types of nested classes (static nested classes, inner classes, local inner classes, and anonymous inner classes) can help you write more organized and efficient Java code.

Comments