Java Inner Classes
Java Inner Classes 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. Inner classes can access the members (including private members) of the outer class.
Types of Inner Classes
- Non-static Nested Class (Inner Class): Associated with an instance of the outer class.
- Static Nested Class: Not associated with an instance of the outer class and can access only static members of the outer class.
- Local Inner Class: Defined within a block, typically a method.
- Anonymous Inner Class: A class without a name, used to instantiate objects with certain "on-the-fly" functionality.
Examples
Example 1: Non-static Inner Class
public class OuterClass {
private String message = "Hello from Outer Class";
class InnerClass {
void display() {
System.out.println(message);
}
}
public static void main(String[] args) {
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.display();
}
}
In this example, InnerClass
is a non-static inner class. It can access the message
field of OuterClass
. An instance of InnerClass
is created using an instance of OuterClass
.
Example 2: Static Nested Class
public class OuterClass {
private static String message = "Hello from Static Nested Class";
static class StaticNestedClass {
void display() {
System.out.println(message);
}
}
public static void main(String[] args) {
OuterClass.StaticNestedClass nested = new OuterClass.StaticNestedClass();
nested.display();
}
}
Here, StaticNestedClass
is a static nested class. It can access the static members of OuterClass
directly. No instance of OuterClass
is needed to create an instance of StaticNestedClass
.
Example 3: Anonymous Inner Class
public class OuterClass {
public static void main(String[] args) {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Running from Anonymous Inner Class");
}
};
new Thread(runnable).start();
}
}
This example demonstrates an anonymous inner class implementing the Runnable
interface. It is used to provide a specific implementation of the run
method on the fly.
Tips and Best Practices
- Use Sparingly: Inner classes can make code harder to read if overused. Use them when they logically belong to the outer class.
- Anonymous Classes: Ideal for implementing interfaces or abstract classes with a small amount of functionality.
- Accessing Members: Inner classes can access all members of the outer class, including private members, making them useful for encapsulation.
- Static Nested Classes: Use when the nested class does not require access to the outer class's instance members.
- Avoid Complexity: Keep inner classes simple to avoid increasing the complexity of the outer class.