Nested and Inner class in Java

Inner class in Java refers to the class that is declared inside another class or interface. In Java, it is possible to nest classes (a class within a class). Like member methods and member variables, a class can have another class as its member. The class defined within another class is called the nested or inner class whereas the class that holds the inner class is called the outer class.

We use inner classes to logically group classes and interfaces at one place to be more maintainable and readable.

Syntax of Inner Class

Following is the syntax to declare a class inside another class. Here, the class DemoOuterClass is the outer class and the class DemoInnerClass is the nested class.

class DemoOuterClass{  
    // statements  
    class DemoInnerClass{  
        //statements
    }  
}

Advantage of Java Inner Classes

  • Inner classes can access all the members of the outer class, including private variables and methods.
  • Nested classes are used to develop more readable and maintainable code as it group logically related classes and interfaces at one place.
  • Optimizing the code module.

There are two types of nested classes in Java. The non-static nested classes are also known as inner classes.

  1. Inner class (Non-static nested class)
  2. Static nested class

Inner Class (Non-static Nested Class)

A non-static nested class(or inner class) is a class defined another class. These are the non-static members of outer class. It has access to members of the outer class. Like any other member variable, we can have access modifier private, protected, public, and default modifier for inner class also.

Since the inner class exists within the outer class, you must create an object of the outer class first, then you can create an object of inner class. Here is an example of how you can declare inner classes in Java.

// Outer class
class Magazine {

    // Nested class
    class Author {
        String authorName = "John";
        public void printAuthorName() {
            System.out.println("Author: " + authorName);
        }
    }
}
public class NestedClass {
    public static void main(String[] args) {
        // Create object of outer class
        Magazine mag = new Magazine();
        // Create object of inner class
        Magazine.Author author = mag.new Author();
        // Call inner class method
        author.printAuthorName();
    }
}
Output
Author: John

In the above program, we declared one inner class named "Author" inside the outer class "Magazine". Inner class "Author" contains a public method "printAuthorName" which prints the value of member variable "authorName". Inside the main method of "NestedClass".

  • We first created an object of an outer class Magazine named mag.
    Magazine mag = new Magazine();
  • Now, by using outer class object mag, we then created an object of inner class "Author" using dot(.) operator. Now, we can use inner class object reference to call printAuthorName method of inner class.
    Magazine.Author author = mag.new Author(); 
    author.printAuthorName();


Accessing Members of Outer Class from Inner Class

As mentioned earlier, an inner class can access all the members of the outer class, including private variables and methods.

Here is a java program to shows how to access the private variable and methods of outer class using inner class.

// Outer class
class Magazine {
    // private variable of outer class
    private int price = 100;
    // private method of outer class
    private String getMagazineName() {
        return "World of Java";
    }
    // Nested class
    class Author {
        String authorName = "John";
        public void printDetails() {
            // Accessing private members of outer class
            System.out.println("Name: " + getMagazineName());
            System.out.println("Price: " + price);
            // Accessing  members of inner class
            System.out.println("Author: " + authorName);
        }
    }
}

public class OuterClassMemberAccess {
    public static void main(String[] args) {
        // Create object of outer class
        Magazine mag = new Magazine();
        // Create object of inner class
        Magazine.Author author = mag.new Author();
        // Call inner class method
        author.printDetails();
    }
}
Output
Name: World of Java
Price: 100
Author: John

In the above program, we have the inner class named "Author" inside the outer class "Magazine". Method "printDetails" of inner class is able to access the variable and methods of outer class.
It is important to note that, although the "getMagazineName()" and "price" are private members of outer class, inner class object was able to access it.


Static Nested Class

A static inner class is a nested class which is a static member of the outer class. It can be accessed without creating an object of the outer class.

Unlike inner class, a static nested class cannot access the member variables of the outer class. It is because the static nested class doesn't require you to create an instance of the outer class.

Syntax of Static Nested Class

class DemoOuterClass{  
    // statements  
    static class DemoInnerClass{  
        //statements
    }  
}

Creating an object of a static nested class is a bit different from instantiating an inner class. Here, we are creating an object of the static nested class by simply using the class name of the outer class.

DemoOuterClass.DemoInnerClass obj = new DemoOuterClass.DemoInnerClass();

Here is a java program for static nested class.

// Outer class
class Bus {
    // Static nested class
    static class Engine {
        public void printDetails() {
            System.out.print("I am a V8 Engine");
        }
    }
}

public class StaticNestedClass {
    public static void main(String[] args) {
        // Create inner class object without
        // creating outer class object
        Bus.Engine engineObject = new Bus.Engine();
        engineObject.printDetails();
    }
}
Output
I am a V8 Engine

In the above program, we have created a static inner class named "Engine" inside outer class "Bus". Inside the main method of StaticNestedClass class, we are creating an object of inner class directly without using object of outer class as follows.

Bus.Engine engineObject = new Bus.Engine();

Important points about inner class

  • Inner class is a member of outer class. They are just like methods and variables declared inside outside class.

  • Since inner class is a member of outer class, you can apply any access modifiers like private, protected to your inner class.

  • You can use the dot (.) notation to access the nested class and its members from outer class.

  • Using the nested class will make your code more readable and provide better maintainability.

  • Non-static inner classes have access to other members(including private members) of the outer class.

Best Practices for Using Nested Classes

While nested classes offer several advantages, it's important to use them judiciously. Here are some best practices:
  • Keep Classes Small and Focused : Avoid creating excessively large nested classes. Each class should have a clear and focused responsibility. If a nested class becomes too complex, consider moving it to its own file.

  • Limit Accessibility : Use the private modifier for nested classes whenever possible. This limits their accessibility and ensures that they are only used within the scope of the outer class.

  • Avoid Deep Nesting : Avoid excessive levels of nesting, as it can make the code difficult to understand. If you find yourself nesting classes deeply, consider refactoring to improve clarity.

  • Prefer Static Nested Classes : If a nested class does not need access to the instance variables and methods of the outer class, consider making it a static nested class. This can improve performance and reduce memory usage.

Conclusion

Nested and inner classes in Java provide a powerful mechanism for organizing code in a modular and hierarchical manner. They improve encapsulation, code organization, and readability. Understanding the types of nested classes and their use cases is essential for effective Java programming.

By applying best practices and using nested classes judiciously, developers can create more maintainable and scalable codebases. Whether it's static nested classes, member inner classes, local inner classes, or anonymous inner classes, each type has its place in Java development. Experiment with nested classes in your projects to leverage their benefits and create well-structured and readable code.