In this tutorial, we will explore the concept of inner classes in Java. Inner classes are a powerful feature that allow you to define one class within another. They can enhance encapsulation, provide better organization, and offer more flexibility in your code structure.
Inner classes are a way to logically group classes together and increase the accessibility of your code. They are especially useful when a class is only used by one other class. By nesting classes, you can keep related classes together and hide them from the outside world if necessary.
In this section, we will cover:
A nested class is a class defined inside another class. The basic syntax for defining a nested class is as follows:
1public class OuterClass {2// Outer class code34class InnerClass {5// Inner class code6};7}
Let's start with a simple example to understand how nested classes work.
1public class OuterClass {23private int outerValue = 10;45class InnerClass {6void display() {7System.out.println("Outer value: " + outerValue);8}9}1011public static void main(String[] args) {12OuterClass outer = new OuterClass();13OuterClass.InnerClass inner = outer.new InnerClass();14inner.display();15}16}
Outer value: 10
In this example, InnerClass is a nested class inside OuterClass. The display method in InnerClass accesses the private variable outerValue of OuterClass.
You can restrict the visibility of inner classes by using the private keyword. This ensures that the inner class cannot be accessed from outside the outer class.
Here's how you can define and use a private nested class.
1public class OuterClass {23private int outerValue = 20;45private class InnerClass {6void display() {7System.out.println("Outer value: " + outerValue);8}9}1011public void createInnerInstance() {12InnerClass inner = new InnerClass();13inner.display();14}1516public static void main(String[] args) {17OuterClass outer = new OuterClass();18outer.createInnerInstance(); // This works19// InnerClass inner = outer.new InnerClass(); // This will cause a compile-time error20}21}
Outer value: 20
In this example, InnerClass is private and can only be accessed within OuterClass. Attempting to create an instance of InnerClass outside OuterClass results in a compile-time error.
private to restrict the access of inner classes.Sometimes, you might want an inner class that doesn't need to access any instance members of the outer class. In such cases, you can define a static inner class using the static keyword.
Here's how you can define and use a static nested class.
1public class OuterClass {23private static int outerValue = 30;45static class InnerClass {6void display() {7System.out.println("Outer value: " + outerValue);8}9}1011public static void main(String[] args) {12OuterClass.InnerClass inner = new OuterClass.InnerClass();13inner.display();14}15}
Outer value: 30
In this example, InnerClass is a static nested class. It can access only the static members of OuterClass. You don't need an instance of OuterClass to create an instance of InnerClass.
An inner class can easily access all members of its enclosing outer class, including private members. This is because an inner class has a reference to its enclosing instance.
Here's how an inner class can access members of its outer class.
1public class OuterClass {23private int outerValue = 40;45class InnerClass {6void display() {7System.out.println("Outer value: " + outerValue);8}9}1011public static void main(String[] args) {12OuterClass outer = new OuterClass();13OuterClass.InnerClass inner = outer.new InnerClass();14inner.display();15}16}
Outer value: 40
In this example, InnerClass accesses the private variable outerValue of OuterClass.
Let's create a practical example that combines the concepts discussed so far. We'll create an Account class with nested Transaction and BalanceChecker classes.
1public class Account {23private double balance;45public Account(double initialBalance) {6this.balance = initialBalance;7}89// Nested Transaction class10class Transaction {11void deposit(double amount) {12balance += amount;13System.out.println("Deposited: " + amount);14}1516void withdraw(double amount) {17if (amount <= balance) {18balance -= amount;19System.out.println("Withdrew: " + amount);20} else {21System.out.println("Insufficient funds");22}23}24}2526// Static nested BalanceChecker class27static class BalanceChecker {28void checkBalance(Account account) {29System.out.println("Current balance: " + account.balance);30}31}3233public static void main(String[] args) {34Account myAccount = new Account(100.0);3536// Using Transaction inner class37Account.Transaction transaction = myAccount.new Transaction();38transaction.deposit(50.0);39transaction.withdraw(30.0);4041// Using BalanceChecker static nested class42Account.BalanceChecker checker = new Account.BalanceChecker();43checker.checkBalance(myAccount);44}45}
Deposited: 50.0 Withdrew: 30.0 Current balance: 120.0
In this example:
Transaction is a nested class that can access the private balance of Account.BalanceChecker is a static nested class that takes an Account instance to check its balance.| Concept | Description |
|---|---|
| Nested Classes | Classes defined inside another class. Can access all members of the outer class. |
| Private Inner Classes | Restricts access to inner classes, making them accessible only within the outer class. |
| Static Inner Classes | Independent of any specific instance of the outer class; can only access static members. |
| Accessing Outer Class | Inner classes have an implicit reference to their enclosing instance and can access all its members. |
In the next section, we will explore Java Abstraction. Abstraction is another fundamental concept in Java that helps you design more flexible and maintainable code. Stay tuned!