Java Inner Class With Example

Inner Class In Java: This post is an extended post of the Core Java tutorial series, where we will discuss Nested Classes and inner classes in Java with the help of examples.

In Java, an inner class is a class that is defined inside another class. Inner classes are a powerful feature of the Java language that allows developers to encapsulate and group related code within a single class. Inner classes have access to the fields and methods of the outer class, which can be useful in many scenarios.

This article will explore the different types of inner classes in Java, their features, and how they can be used to write cleaner and more maintainable code.

What Is Inner Class In Java?

Nested classes or inner classes refer to a class inside another class. Similar to how a class has members such as variables and methods, an inner class is also a member that can be a class. A top-level or outer class has other classes as its members and can contain multiple inner classes.

The need for using an inner class in Java can be explained through the following points:

Logical Grouping Of Similar Classes: Firstly, it helps to group classes that are related to each other logically. For instance, if a class is only useful to a single class, we can embed both classes together. It will help their package to be more streamlined.

Increase Encapsulation: Using an inner class in your Java programs can help you to increase encapsulation, especially when one class needs to access private members of another class. By nesting the class that needs access within the other class, the members of the outer class can be declared private, and the inner class can access them while being protected from the outside world. This enhances security and encapsulation.

Increase Readability And Maintainability: Placing inner classes within top-level classes can increase the readability and maintainability of the code by bringing the code closer to where it is being used.

Types of Nested Class

Java provides four types of inner classes, each with its own unique features and use cases. This section will explore each type of inner class and provide examples to illustrate their usage.

Java Nested Class

Non-Static Nested Class

Non-static nested classes are also known as inner classes because they are defined inside another class. Inner classes have access to the fields and methods of the outer class, including private fields and methods. Inner classes can group related functionality and encapsulate it within a single class.

As the inner class is associated with the outer class object or instance, we can’t declare static variables inside the inner class.

package com.softwaretestingo.InnerClass;
public class NonStaticNestedClassEx1 
{
	private int x= 1;
	public void innerInstance()
	{
		innerclass inner = new innerclass();
		inner.seeOuter();
	}
	public static void main(String[] args) 
	{
		NonStaticNestedClassEx1 obj=new NonStaticNestedClassEx1();
		obj.innerInstance();
	}
	//Inner Class Example
	class innerclass
	{
		public void seeOuter () 
		{
			System.out.println("Outer Value of x is :" + x);
		}
	}
}

Output:

Outer Value of x is :1

Accessing Members of the Outer Class within the Inner Class

As we have discussed, we can access the members of the outer class from an inner class using this keyword. As we have mentioned above, the object of Java’s inner class is a part of the outer class object, So to create an instance of the inner class, firstly, we need to create an instance of the outer class.

You can instantiate the inner class like below:

OuterClass outerObject = new OuterClass();
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

Let us see an example to understand very easily:

package com.softwaretestingo.InnerClass;
public class NonStaticNestedClassEx2 
{
	// private variable of the outer class
	private int value = 50;

	// inner class
	class JavaInnerClass
	{
		// public variable of the inner class
		public int getValue()
		{
			System.out.println("getValue method of inner class is called");
			return value;
		}
	}
	public static void main(String[] args) 
	{
		//Creating object of outer class
		NonStaticNestedClassEx2 obj=new NonStaticNestedClassEx2();
		
		//Creating object of inner class
		NonStaticNestedClassEx2.JavaInnerClass innerobj=obj.new JavaInnerClass();
		System.out.println("Value : " + innerobj.getValue());
	}
}

Output:

getValue method of inner class is called
Value : 50

Static Nested Classes

When a nested class is static, it is known as a static nested class. These classes have access only to the static members of the outer class. Essentially, a static nested class is no different from any other top-level class; it is nested solely for the purpose of packaging convenience.

Syntax For Static-Nested Classes

class OuterClass 
{
	// ...

	static class StaticNestedClass 
	{
		// ...
	}
}

The following statement can be used to create a static class object.

OuterClass.StaticNestedClass nested = new OuterClass.StaticNestedClass();

Let us see an example for a better understanding:

Example 1:

package com.softwaretestingo.InnerClass;
public class StaticNestedClassEx 
{
	//Static Nested Class
	static class NestedDemo
	{
		public void myMethod()
		{
			System.out.println("Static nested class method is called");
		}
	}
	public static void main(String[] args) 
	{
		//Accessing the static nested class without initializing the object of Outer class
		StaticNestedClassEx.NestedDemo obj= new StaticNestedClassEx.NestedDemo();
		obj.myMethod();
	}
}

Output:

Static nested class method is called

Example 2:

Let us see another example where we try to access a non-static variable inside a static class:

package com.softwaretestingo.InnerClass;
public class StaticNestedClassEx2 
{
	// static member
	static int outer_x = 10;

	// instance(non-static) member
	int outer_y = 20;

	// private member
	private static int outer_private = 30;

	// static nested class
	static class StaticNestedClass
	{
		void display()
		{
			// can access static member of outer class
			System.out.println("outer_x = " + outer_x);

			// can access display private static member of outer class
			System.out.println("outer_private = " + outer_private);

			// The following statement will give compilation error
			// as static nested class cannot directly access non-static membera
			// System.out.println("outer_y = " + outer_y);
		}
	}
	public static void main(String[] args) 
	{
		//Accessing a static nested class
		StaticNestedClassEx2.StaticNestedClass obj= new StaticNestedClassEx2.StaticNestedClass();
		obj.display();
	}
}

Output:

outer_x = 10
outer_private = 30

Local Inner Classes

A class defined within a method body is called a local inner class. Because a local inner class is not associated with an object, it cannot use access modifiers like private, public, or protected. The only allowed modifiers for a local inner class are abstract or final. Despite this limitation, a local inner class has access to all the members of the enclosing class and local final variables within the scope in which it is defined.

Additionally, it can access non-final local variables of the method in which it is defined, but it cannot modify them. Therefore, attempting to print the value of a non-final local variable’s value is permitted, but changing its value from within the method’s local inner class will result in a compile-time error.

The inner class can access the fields of the outer class, but the local class must be instantiated in the block where they are defined.

Rules Of Inner Class

  • They cannot have access modifiers(public, private, protected) in their declaration.
  • The only modifiers you can use with local inner class declarations are abstract and final.
  • They can access any member of the outer class, whether static, private, or anything else.
  • These classes can only define non-static members inside them.
  • They can access only the final variables of its enclosing method. Accessing non-final variables of its enclosing methods will result in a compilation error.
  • The scope of the inner class is restricted within the block where they are defined.
  • You can not instantiate the local inner class outside the block where it is defined.
  • A local class can access the members of its local inner class.
  • An abstract class can extend local inner classes or implement an interface.

How to Declare a Local Inner-Class

We can declare a local inner class within a block, a method’s body, a for loop, or an if statement.

What Happens when you compile

When a program with a local inner class is compiled, two .class files will be generated: one is for the outer class, and one is for the inner class, but the inner class has the reference to the outer class.

Example1:

package com.softwaretestingo.InnerClass;
public class LocalInnerClassEx 
{
	int outerVariable = 100;
	static int staticOuterVariable = 200;

	//Outer Class method
	public int outerClassMethod()
	{
		System.out.println("Outer Class method is Executed");
		int localVar = 50;
		final int finalLocalVariable = 60;   

		//Create Local Inner Class
		class LocalInnerClass
		{
			int innerVariable = 20;

			int getSum(int parameter)
			{
				// Cannot access localVar here as it's not declared as final
				return outerVariable + staticOuterVariable + finalLocalVariable +
						innerVariable + parameter;
			}
		}
		
		//Local Class will be instantiated with in the Block
		LocalInnerClass localobj=new LocalInnerClass();
		return localobj.getSum(20);

	}
	public static void main(String[] args) 
	{
		LocalInnerClassEx outerObj=new LocalInnerClassEx();
		int total=outerObj.outerClassMethod();

		System.out.println("The Total Value is: "+total);
	}
}

Output:

Outer Class method is Executed
The Total Value is: 400

Anonymous Inner Class

These are inner classes that do not have a name and are defined at the same time as they are instantiated. It is defined and instantiated in a single statement and always extends a class or implements an interface. Due to the lack of a name, it is impossible to define a constructor for an anonymous inner class. These inner classes are only accessible at the point where they are defined. Although creating an anonymous inner class can be challenging to define, the test program below will demonstrate its practical usage.

The main objective of anonymous inner classes is “just for instant use”. We may use the java anonymous class in 3 ways.

  • The anonymous inner class extends a class.
  • The anonymous inner class that implements an interface
  • The anonymous inner class is defined as arguments of the method/constructor

Let us Go through some examples to understand the uses of Anonymous Inner Class.

Anonymous Inner Class That Extends A Class

package com.softwaretestingo.InnerClass;
//This is Example Of Anonymous Inner Class That Extends A Class
class greeting
{
	public void sayHello()
	{
		System.out.println("Say Hello To All");
	}
}
public class AnonymousInnerClassEx 
{
	public static void main(String[] args) 
	{
		//Anonymous Inner class 1
		greeting engObj=new greeting()
		{
			// This is equivalent code of extending greeting class and then overriding sayHello() method
			public void sayHello()
			{
				System.out.println("Hello");
			}

		};
		
		//Anonymous Inner class 2
		greeting hindiObj=new greeting()
		{
			// This is equivalent code of extending greeting class and then overriding sayHello() method
			public void sayHello()
			{
				System.out.println("Namaste");
			}
		};
		//This will call Anonymous Inner class 1 Method
		engObj.sayHello();
		
		//This will call Anonymous Inner class 2 Method
		hindiObj.sayHello();

		//Call outer class method
		greeting obj=new greeting();
		obj.sayHello();
	}
}

Output:

Hello
Namaste
Say Hello To All

An anonymous inner class that implements an interface

package com.softwaretestingo.InnerClass;
//Java anonymous class that implements an interface
public class AnonymousInnerClassEx2 
{
	public static void main(String[] args) 
	{
		// Implementing Runnable Interface and overriding run()
		Runnable r = new Runnable() 
		{
			public void run() 
			{
				for (int i = 0; i < 5; i++) 
				{
					System.out.println("Test Thread");
				}
			}
		};
		Thread thread = new Thread(r);
		thread.start();
		for (int i = 0; i < 4; i++) 
		{
			System.out.println("Main Thread");
		}
	}
}

Output:

Main Thread
Main Thread
Main Thread
Main Thread
Test Thread
Test Thread
Test Thread
Test Thread
Test Thread

An anonymous inner class that is defined as arguments of method/constructor

package com.softwaretestingo.InnerClass;
//Java Anonymous class as argument of method / constructor
public class AnonymousInnerClassEx3 
{
	public static void main(String[] args) 
	{
		// Anonymous inner class as constructor argument
		new Thread( new Runnable() 
		{
			public void run()
			{
				for(int i=0; i<5; i++) 
				{
					System.out.println("Test Thread");
				}
			}
		}).start();
		for(int i=0; i<5; i++)
		{
			System.out.println("Main Thread");
		}
	}
}

Output:

Main Thread
Main Thread
Test Thread
Test Thread
Test Thread
Test Thread
Test Thread
Main Thread
Main Thread
Main Thread

Key points about the Anonymous Inner Class

  • They cannot have access modifiers(public, private, protected) in their declaration.
  • These classes end with a semicolon(;) after curly braces }.
  • They can access any member of the outer class, whether static, private, or anything else.
  • These classes can only define non-static members inside it, not static members.
  • This is the only type of inner class that cannot define constructors since it doesn’t have a name.
  • These classes can be defined as a parameter inside a method as well.

I hope the above tutorial helps you understand the importance and use of Java inner class; if you have found any mistakes or want to suggest more improvement, you can write in the comment section.

Ref: article

What is the difference between the inner class and the subclass?

An inner class is a class that is nested or defined within another class. On the other hand, a subclass is a class that is derived from another class. Moreover, while an inner class can only be accessed using the reference of the outer class within which it is nested, a subclass can be accessed directly unless the subclass has inherited private variables.

Can we write a class inside a class in Java?

Yes, we can define a class within another class in Java. Such a class is known as a nested class, and it allows us to logically organize classes in one place, thereby creating a more maintainable and readable code. As part of its enclosing class, a nested class can be declared public, private, package-private, or protected.

Can Java inner class be private?

Yes, a Java inner class can be private. However, once an inner class is declared private, it cannot be accessed from an object outside the class. Inner and outer classes can access each other’s private instance variables and methods. Private and public modifiers have the same effect as long as we are within the outer or inner class.

I love open-source technologies and am very passionate about software development. I like to share my knowledge with others, especially on technology that's why I have given all the examples as simple as possible to understand for beginners. All the code posted on my blog is developed, compiled, and tested in my development environment. If you find any mistakes or bugs, Please drop an email to softwaretestingo.com@gmail.com, or You can join me on Linkedin.

Leave a Comment