In Java, you can define a class inside another class. These are called **inner classes**. By nesting classes, you can visually group helpers that only serve the outer class, enhancing encapsulation and keeping your package namespaces clean.
In this guide, we will look at three types of nested classes: Member Inner Classes, Local Inner Classes, and Anonymous Inner Classes.
Imagine a house (Outer Class):
- Member Inner Class: A light switch on the kitchen wall. It has access to all the house's power lines and cannot exist without the house.
- Local Inner Class: A temporary space heater you set up inside the kitchen during winter. It only exists while you are in the kitchen cooking.
- Anonymous Inner Class: A hired repairman who arrives, fixes a faucet once without introducing themselves, and leaves. They have no name and perform a one-time job.
1. Member Inner Classes
A member inner class is declared directly inside the body of the outer class. It has access to all private variables of the outer class:
class MemberInnerClass {
private int data = 30;
class Inner {
void msg() {
// Can access private field 'data' directly
System.out.println("data is " + data);
}
}
public static void main(String args[]) {
MemberInnerClass obj = new MemberInnerClass();
// Syntactic requirement to construct an inner class instance
MemberInnerClass.Inner in = obj.new Inner();
in.msg(); // Prints: data is 30
}
}
2. Local Inner Classes
A local inner class is declared inside a specific method body. It is only scope-visible inside that method:
class LocalInner {
private int data = 30;
void display() {
// Local class declared inside method
class Local {
void msg() {
System.out.println(data);
}
}
Local l = new Local();
l.msg();
}
public static void main(String args[]) {
LocalInner obj = new LocalInner();
obj.display(); // Prints: 30
}
}
3. Anonymous Inner Classes
An anonymous inner class has no name. You declare and instantiate it simultaneously, typically to override interface methods or abstract classes on the fly:
abstract class Person {
abstract void eat();
}
class AnonymousInner {
public static void main(String args[]) {
// Declares and instantiates anonymous Person subclass
Person p = new Person() {
void eat() {
System.out.println("nice fruits");
}
};
p.eat(); // Prints: nice fruits
}
}
Conclusion
Use inner classes to restrict helper access. Member inner classes represent permanent components, local classes restrict scope to methods, and anonymous classes are ideal for quick, one-off callbacks.