In Java, nested classes are classes that are defined within another class. There are several types of nested classes in Java, including static nested classes and inner classes. Understanding nested and inner classes is essential as they provide powerful ways to design your applications in a more organized and efficient manner.
This guide will cover the different types of nested and inner classes in Java, their uses, and practical examples.
A nested class is a class that is defined inside another class. In Java, you can declare both static and non-static (inner) nested classes. Nested classes are used to logically group classes that belong together and can be beneficial in terms of encapsulation.
Java provides several types of nested classes. Each type has its specific use cases and behavior.
A static nested class is a nested class that is defined with the static
keyword. It is not associated with an instance of the outer class, meaning it can be instantiated independently of the outer class object.
class OuterClass {
private static String staticMessage = "Hello from static outer class!";
static class StaticNestedClass {
void display() {
System.out.println(staticMessage); // Accessing static member of outer class
}
}
}
public class Main {
public static void main(String[] args) {
// Creating an instance of the static nested class
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
nestedObject.display(); // Output: Hello from static outer class!
}
}
In this example, the StaticNestedClass
is a static nested class inside OuterClass
. It can access the static members of OuterClass
, but not the instance members.
An inner class is a non-static nested class. Unlike static nested classes, inner classes are associated with an instance of the outer class, which means they can access both the static and non-static members of the outer class.
A member inner class is a non-static nested class that is defined within the body of the outer class. It can access all the members of the outer class.
class OuterClass {
private String outerMessage = "Hello from the outer class!";
class MemberInnerClass {
void display() {
System.out.println(outerMessage); // Accessing non-static member of outer class
}
}
}
public class Main {
public static void main(String[] args) {
// Creating an instance of the outer class
OuterClass outer = new OuterClass();
// Creating an instance of the member inner class
OuterClass.MemberInnerClass inner = outer.new MemberInnerClass();
inner.display(); // Output: Hello from the outer class!
}
}
In this example, the MemberInnerClass
is a non-static nested class defined inside the OuterClass
. It has access to the non-static member outerMessage
of the outer class.
A local inner class is a class that is defined within a method of the outer class. This type of inner class is only accessible within the method where it is defined.
class OuterClass {
void outerMethod() {
// Local inner class defined inside the method
class LocalInnerClass {
void display() {
System.out.println("This is a local inner class!");
}
}
// Creating an instance of the local inner class
LocalInnerClass localInner = new LocalInnerClass();
localInner.display(); // Output: This is a local inner class!
}
}
public class Main {
public static void main(String[] args) {
// Creating an instance of the outer class and calling the outer method
OuterClass outer = new OuterClass();
outer.outerMethod();
}
}
Here, the LocalInnerClass
is defined within the outerMethod
. It can only be used within this method and has no visibility outside of it.
An anonymous inner class is a special type of inner class that is defined without a name. It is often used when you need to instantiate a class that implements an interface or extends a class, but you don't want to create a separate named class for it.
interface Greeting {
void sayHello();
}
public class Main {
public static void main(String[] args) {
// Anonymous inner class implementing Greeting interface
Greeting greet = new Greeting() {
public void sayHello() {
System.out.println("Hello from anonymous inner class!");
}
};
greet.sayHello(); // Output: Hello from anonymous inner class!
}
}
In this example, the anonymous inner class implements the Greeting
interface. It is instantiated and used immediately without defining a separate named class.
class Outer {
static class Nested {
void show() {
System.out.println("Inside Static Nested Class");
}
}
}
public class Main {
public static void main(String[] args) {
Outer.Nested obj = new Outer.Nested();
obj.show();
}
}
class Outer {
private String message = "Hello from Outer Class!";
class Inner {
void printMessage() {
System.out.println(message);
}
}
}
public class Main {
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.printMessage();
}
}
interface Vehicle {
void drive();
}
public class Main {
public static void main(String[] args) {
Vehicle car = new Vehicle() {
public void drive() {
System.out.println("Driving car...");
}
};
car.drive(); // Output: Driving car...
}
}