(Translated by https://www.hiragana.jp/)
Inner Class in Java - GeeksforGeeks
Open In App

Inner Class in Java

Last Updated : 28 Jul, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

In Java, an inner class is a class defined within another class or interface. It groups logically related classes, enhancing encapsulation and making code more readable and aligned with real-world object-oriented design.

Features of Inner Class

  • Making code clean and readable.
  • Private methods of the outer class can be accessed, so bringing a new dimension and making it closer to the real world.
  • Optimizing the code module.

We do use them often as we go advance in java object-oriented programming where we want certain operations to be performed, granting access to limited classes and many more which will be clear as we do discuss and implement all types of inner classes in Java.

Example:

public class OuterClass {

    // Inner class
    class InnerClass {
        void display() {
            System.out.println("Hello from Inner Class!");
        }
    }

    public static void main(String[] args) {
        // Create OuterClass object
        OuterClass outer = new OuterClass();

        // Create InnerClass object using OuterClass
        OuterClass.InnerClass inner = outer.new InnerClass();

        // Call method
        inner.display();
    }
}

Output
Hello from Inner Class!

Types of Inner Classes

There are basically four types of inner classes in java.

  1. Nested Inner Class
  2. Method Local Inner Classes
  3. Static Nested Classes
  4. Anonymous Inner Classes
innerclass
InnerClass

Let us discuss each of the above following types sequentially in-depth alongside a clean java program which is very crucial at every step as it becomes quite tricky as we adhere forwards.

Type 1: Nested Inner Class 

It can access any private instance variable of the outer class. Like any other instance variable, we can have access modifier private, protected, public and default modifier. Like class, an interface can also be nested and can have access specifiers. 

Example

//outer class
class Outer {

    // Simple nested inner class
    class Inner {

        // show() method of inner class
        public void show()
        {

            System.out.println("In a nested class method");
        }
    }
}

// Class 2 - Main class
class Main {

    // Main driver method
    public static void main(String[] args)
    {

        // Note how inner class object is created inside main()
        Outer.Inner in = new Outer().new Inner();

        // Calling show() method over above object created
        in.show();
    }
}

Output
In a nested class method

Note:  We can not have a static method in a nested inner class because an inner class is implicitly associated with an object of its outer class so it cannot define any static method for itself. For example, the following program doesn't compile. But Since JAVA Version 16 we can have static members in our inner class also.

Example:

// Class 1
// Outer class
class Outer {

    // Method defined inside outer class
    void outerMethod()
    {

        // Print statement
        System.out.println("inside outerMethod");
    }

    // Class 2
    // Inner class
    class Inner {

        // Main driver method
        public static void main(String[] args)
        {

            // Display message for better readability
            System.out.println("inside inner class Method");
        }
    }
}

Output:


Output
Output


An interface can also be nested and nested interfaces have some interesting properties. We will be covering nested interfaces in the next post.

Type 2: Method Local Inner Classes 

Inner class can be declared within a method of an outer class which we will be illustrating in the below example where Inner is an inner class in outerMethod().

Example 1:

// Class 1 Outer class
class Outer {

    // Method inside outer class
    void outerMethod()
    {

        // Print statement
        System.out.println("inside outerMethod");

        // Class 2
        class Inner {

            // Method defined inside inner class
            void innerMethod()
            {

                // Print statement whenever inner class is called
                System.out.println("inside innerMethod");
            }
        }

        // Creating object of inner class
        Inner y = new Inner();

        // Calling over method defined inside it
        y.innerMethod();
    }
}

// Class 3 Main class
class GFG {

    // Main driver method
    public static void main(String[] args)
    {

        // Creating object of outer class inside main() method
        Outer x = new Outer();

        // Calling over the same method as we did for inner class above
        x.outerMethod();
    }
}

Output
inside outerMethod
inside innerMethod

Method Local inner classes can’t use a local variable of the outer method until that local variable is not declared as final. For example, the following code generates a compiler error. 

Note: "x" is not final in outerMethod() and innerMethod() tries to access it.

Example 2:

class Outer {
   void outerMethod() {
      int x = 98;
      System.out.println("inside outerMethod");
      class Inner {
         void innerMethod() {
            System.out.println("x= "+x);
         }
      }
      Inner y = new Inner();
      y.innerMethod();
   }
}
class MethodLocalVariableDemo {
   public static void main(String[] args) {
      Outer x=new Outer();
      x.outerMethod();
   }
}

Output
inside outerMethod
x= 98

Note: Local inner class cannot access non-final local variable till JDK 1.7. Since JDK 1.8, it is possible to access the non-final local variable in method local inner class. 

But the following code compiles and runs fine (Note that x is final this time) 

Example 3:

class Outer {
   void outerMethod() {
      final int x=98;
      System.out.println("inside outerMethod");
      class Inner {
         void innerMethod() {
            System.out.println("x = "+x);
         }
      }
      Inner y = new Inner();
      y.innerMethod();
   }
}
class MethodLocalVariableDemo {
    public static void main(String[] args){
      Outer x = new Outer();
      x.outerMethod();
    }
}

Output
inside outerMethod
x = 98

The main reason we need to declare a local variable as a final is that the local variable lives on the stack till the method is on the stack but there might be a case the object of the inner class still lives on the heap. 
Method local inner class can’t be marked as private, protected, static and transient but can be marked as abstract and final, but not both at the same time.

Type 3: Static Nested Classes

A static class defined inside another class. It cannot access non-static members of the outer class directly. 

Example:

import java.util.*;

// Class 1 Outer class
class Outer {

    // Method
    private static void outerMethod()
    {

        // Print statement
        System.out.println("inside outerMethod");
    }

    // Class 2 Static inner class
    static class Inner {

        public static void display()
        {

            // Print statement
            System.out.println("inside inner class Method");

            // Calling method inside main() method
            outerMethod();
        }
    }
}

// Class 3 Main class
class GFG {

    // Main driver method
    public static void main(String args[])
    {

        // Calling method static display method rather than an instance of that class.
        Outer.Inner.display();
    }
}

Output
inside inner class Method
inside outerMethod

Type 4: Anonymous Inner Classes 

Anonymous inner classes are declared without any name at all. They are created in two ways. 

  • As a subclass of the specified type
  • As an implementer of the specified interface

Way 1: As a subclass of the specified type 

Example:

import java.util.*;

// Class 1 Helper class
class Demo {

    // Method of helper class
    void show()
    {
        // Print statement
        System.out.println(
            "i am in show method of super class");
    }
}

// Class 2 Main class
class Flavor1Demo {

    //  An anonymous class with Demo as base class
    static Demo d = new Demo() {
        // Method 1 show() method
        void show()
        {
            // Calling method show() via super keyword which refers to parent class
            super.show();

            // Print statement
            System.out.println("i am in Flavor1Demo class");
        }
    };

    // Method 2 Main driver method
    public static void main(String[] args)
    {
        // Calling show() method inside main() method
        d.show();
    }
}

Output
i am in show method of super class
i am in Flavor1Demo class

Explanation:

  • Demo is a class with a show() method.
  • Flavor1Demo uses an anonymous inner class to extend Demo and override its show() method.
  • Inside the new show()
  • super.show() calls the original method from Demo.
  • Then a new message is printed.

Way 2: As an implementer of the specified interface  

Example:

// Interface
interface Hello {

    // Method defined inside interface
    void show();
}

// Main class
class GFG {

    // Class implementing interface
    static Hello h = new Hello() {
      
        // Method 1 show() method inside main class
        public void show()
        {
            // Print statement
            System.out.println("i am in anonymous class");
        }
    };

    // Method 2 Main driver method
    public static void main(String[] args)
    {
        // Calling show() method inside main() method
        h.show();
    }
}

Explanation:

  • Hello is an interface with one abstract method show().
  • Inside class GFG, an anonymous inner class implements Hello.
  • The show() method is overridden to print a custom message.
  • h.show() is called in the main() method to execute the overridden logic.

Implementation of Inner Class

public class OuterClass {
    private int outerVar;

    public OuterClass(int var) {
        outerVar = var;
    }

    public void outerMethod() {
        System.out.println("This is an outer method");
    }

    // Inner class
    public class InnerClass {
        private int innerVar;

        public InnerClass(int var) {
            innerVar = var;
        }

        public void innerMethod() {
            System.out.println("This is an inner method");
        }

        public void accessOuterVar() {
            System.out.println("Outer variable from inner class: " + outerVar);
        }
    }

    public static void main(String[] args) {
        // Create an instance of the outer class
        OuterClass outer = new OuterClass(10);

        // Create an instance of the inner class
        OuterClass.InnerClass inner = outer.new InnerClass(20);

        // Access the inner class methods
        inner.innerMethod();
        inner.accessOuterVar();
    }
}

Output
This is an inner method
Outer variable from inner class: 10

Explanation:

  • OuterClass has a private variable outerVar and a method outerMethod().
  • It defines a non-static inner class InnerClass which has its own variable and methods.
  • InnerClass can access members of OuterClass, including the private variable outerVar.
  • In the main() method, we first create an instance of OuterClass, then use it to create an instance of InnerClass.

Benefits of using inner classes in Java are:

  • Encapsulation: Inner classes can access private variables and methods of the outer class. This helps to achieve encapsulation and improves code readability.
  • Code Organization: Inner classes allow you to group related code together in one place. This makes your code easier to understand and maintain.
  • Better Access Control: Inner classes can be declared as private, which means that they can only be accessed within the outer class. This provides better access control and improves code security.
  • Callbacks: Inner classes are often used for implementing callbacks in event-driven programming. They provide a convenient way to define and implement a callback function within the context of the outer class.
  • Polymorphism: Inner classes can be used to implement polymorphism. You can define a class hierarchy within the outer class and then create objects of the inner classes that implement the different subclasses.
  • Reduced Code Complexity: Inner classes can reduce the complexity of your code by encapsulating complex logic and data structures within the context of the outer class.

Overall, the use of inner classes can lead to more modular, maintainable and flexible code.


Article Tags :
Practice Tags :

Similar Reads