In Java, inner classes and nested classes are used to logically group classes and interfaces within a single unit. They help in encapsulation and can lead to more readable and maintainable code. Let’s explore these concepts in detail:
1. Nested Classes
A nested class is a class defined within another class. There are two types of nested classes:
- Static Nested Classes
- Non-Static Nested Classes (Inner Classes)
2. Static Nested Classes
- Declared with the
static
keyword. - Belongs to the outer class, not to instances of the outer class.
- Can access only static members of the outer class.
- Can be instantiated without an instance of the outer class.
Example:
public class OuterClass {
static int outerStaticVar = 10;
int outerInstanceVar = 20;
static class StaticNestedClass {
void display() {
System.out.println("Outer static variable: " + outerStaticVar);
// System.out.println("Outer instance variable: " + outerInstanceVar); // Error: Cannot access non-static members
}
}
public static void main(String[] args) {
OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass(); // No need for OuterClass instance
nestedObj.display(); // Output: Outer static variable: 10
}
}
3. Non-Static Nested Classes (Inner Classes)
- Declared without the
static
keyword. - Belongs to an instance of the outer class.
- Can access both static and non-static members of the outer class.
- Requires an instance of the outer class to be instantiated.
Example:
public class OuterClass {
int outerVar = 30;
class InnerClass {
void display() {
System.out.println("Outer variable: " + outerVar); // Can access outer instance variable
}
}
public static void main(String[] args) {
OuterClass outerObj = new OuterClass();
OuterClass.InnerClass innerObj = outerObj.new InnerClass(); // Requires OuterClass instance
innerObj.display(); // Output: Outer variable: 30
}
}
4. Types of Inner Classes
Inner classes can be further categorized into:
- Member Inner Class
- Local Inner Class
- Anonymous Inner Class
a. Member Inner Class
- Defined at the member level of the outer class (like methods or variables).
- Can access all members of the outer class.
Example:
public class OuterClass {
private int outerVar = 40;
class MemberInnerClass {
void display() {
System.out.println("Outer variable: " + outerVar);
}
}
public static void main(String[] args) {
OuterClass outerObj = new OuterClass();
OuterClass.MemberInnerClass innerObj = outerObj.new MemberInnerClass();
innerObj.display(); // Output: Outer variable: 40
}
}
b. Local Inner Class
- Defined inside a block, such as a method or a constructor.
- Can only access
final
or effectively final local variables of the enclosing block.
Example:
public class OuterClass {
void outerMethod() {
final int localVar = 50;
class LocalInnerClass {
void display() {
System.out.println("Local variable: " + localVar);
}
}
LocalInnerClass innerObj = new LocalInnerClass();
innerObj.display(); // Output: Local variable: 50
}
public static void main(String[] args) {
OuterClass outerObj = new OuterClass();
outerObj.outerMethod();
}
}
c. Anonymous Inner Class
- A class without a name, defined and instantiated in a single expression.
- Commonly used for overriding methods of a class or interface.
Example:
interface Greeting {
void greet();
}
public class OuterClass {
public static void main(String[] args) {
Greeting greeting = new Greeting() { // Anonymous inner class
@Override
public void greet() {
System.out.println("Hello from anonymous inner class!");
}
};
greeting.greet(); // Output: Hello from anonymous inner class!
}
}
5. Key Differences Between Static and Non-Static Nested Classes
Feature | Static Nested Class | Non-Static Nested Class (Inner Class) |
---|---|---|
Declaration | Declared with static keyword | Declared without static keyword |
Instance Requirement | No instance of outer class required | Requires an instance of the outer class |
Access to Members | Can access only static members of outer class | Can access both static and non-static members of outer class |
Memory Usage | More memory-efficient | Less memory-efficient (tied to outer instance) |
6. When to Use Inner and Nested Classes
- Use static nested classes when:
- The nested class doesn’t need access to instance variables of the outer class.
- You want to group related classes logically.
- Use inner classes when:
- The nested class needs access to instance variables of the outer class.
- You want to encapsulate functionality within the outer class.
7. Example Combining Inner and Nested Classes
public class OuterClass {
private int outerVar = 60;
static int outerStaticVar = 70;
class InnerClass {
void display() {
System.out.println("Outer variable: " + outerVar);
}
}
static class StaticNestedClass {
void display() {
System.out.println("Outer static variable: " + outerStaticVar);
}
}
public static void main(String[] args) {
// Inner class example
OuterClass outerObj = new OuterClass();
OuterClass.InnerClass innerObj = outerObj.new InnerClass();
innerObj.display(); // Output: Outer variable: 60
// Static nested class example
OuterClass.StaticNestedClass nestedObj = new OuterClass.StaticNestedClass();
nestedObj.display(); // Output: Outer static variable: 70
}
}
By understanding inner and nested classes, you can design more modular and encapsulated Java programs!