Inner classes in Java are classes that are defined within the scope of another class. They are sometimes referred to as nested classes because they are nested within the body of another class. Inner classes can access the members (including private members) of the enclosing class and can be instantiated just like any other class.
Declaring a class inside a class is called an inner class.
class Outer{
class Inner{
—-----
}
}
Inner class can be declared as :
- private class
- static class
Benefits of Using Inner class
In Java applications, inner classes are able to provide the following advantages.
- Modularization
- Abstraction
- Security
- Shareability
- Reusability
Modularization
In general, in Java applications to provide modularization we will use the features like modules, packages,….
Inside a class if we want to organize the code as per the modules then we have to use inner classes.
class Maths{
—----
class Algebra{
—------
}
class Trigonometry{
—-----
}
class Calculus{
—---
}
class Geometry{
—----
}
}
Abstraction
If we declare a member inside an inner class then that member is having the scope up to the respective inner class only, it is not visible outside of the inner class, so inner classes are able to hide their internal declarations, so inner classes are able to provide abstraction.
class A{
class B{
int i = 10;
}
class C{
i = i + 10; —---> Error
}
}
Security
In general, in Java applications, It is not possible to declare outer classes as private, but it is possible to declare inner classes as private, so inner classes are able to provide security.
class A {
private class B {
}
}
Shareability
In Java applications, it is not possible to declare outer classes as static , but it is possible to declare an inner class as static, so inner classes are able to provide shareability.
class A {
static class B {
}
}
Reusability
In java applications, it is possible to define inheritance relationships between inner classes, so inner classes are able to provide Reusability.
class A {
// inner class
class B {
—----
}
// inheritance relationship between inner classes
class C extends B {
—----
}
}
If we compile a java file that contains outer classes and inner classes then the compiler will generate separate .class files for the outer classes and the separate .class files for the inner classes.
Outer class : Outer.class
Inner Class : Outer$Inner.class
Types of Inner classes
In Java, there are four types of Inner classes.
- Member Inner Classes
- Static Inner Classes
- Method Local Inner Classes
- Anonymous Inner Classes
Member Inner Classes
Declaring a non-static inner class inside a class is called a member inner class.
Syntax:
class Outer {
class Inner {
—----
}
}
–> If we declare variables and methods inside an inner class then we are able to access those variables and methods by creating an object for the inner class.
To create an object for the member inner class we have to use the following syntax.
Outer.Inner refVar = new Outer().new Inner();
- In Java applications, by using the outer class reference variables we are able to access only outer class members, we are unable to access inner class members.
- In Java applications, by using inner class reference variables we are able to access only inner class members , we are unable to access outer class members.
–> In Java applications, we are able to access all the outer class members inside the inner classes , but we are unable to access all the inner class members inside the outer class.
→ Inside the inner classes, by default static declarations are not allowed, but static declarations are possible along with the final keyword.
class A{
int i = 10;
void m1(){
System.out.println("m1-A");
/*System.out.println(j);
m2();*/
}
class B{
int j = 20;
//static int k = 30; ---> Error: Static not allowed
static final int l = 40; ---> Valid : static final allowed
void m2(){
System.out.println("m2-B");
System.out.println(i);
m1();
}
}
}
public class Main {
public static void main(String[] args){
A a = new A();
System.out.println(a.i);
a.m1();
/* System.out.println(a.j);
a.m2();*/
A.B ab = new A().new B();
System.out.println(ab.j);
ab.m2();
/*System.out.println(ab.i);
ab.m1();*/
A.B ab1 = a.new B();
ab1.m2();
System.out.println(ab1.j);
}
}
Inheritance over the inner classes
In java applications, it is possible to define inheritance relations between the inner classes with the following cases.
Case#1 : Extend one inner class to another inner class
We can extend one inner class to another class but both the inner classes must be available in the same outer class.
class A {
class B {
}
class C extends B {
}
}
class A{
class B{
void m1(){
System.out.println("m1-B");
}
}
class C extends B{
void m2(){
System.out.println("m2-C");
}
}
}
public class Main {
public static void main(String[] args){
A.B ab = new A().new B();
ab.m1();
A.C ac = new A().new C();
ac.m1();
ac.m2();
}
}
m1-B
m1-B
m2-C
class A{
class B{
}
}
// outside of class A
class C{
class D extends A.B{
}
}
Status: Invalid
Case#2 : Extend a normal class to an inner class existing in an outer class.
class A{
void m1(){
System.out.println("m1-A");
}
}
// normal class extended to an inner class existing in an outer class
class B{
class C extends A{
void m2(){
System.out.println("m2-C");
}
}
}
public class Main {
public static void main(String[] args){
A a = new A();
a.m1();
B.C bc = new B().new C();
bc.m1();
bc.m2();
}
}
m1-A
m1-A
m2-C
Case#3 : Extend an outer class to the respective inner class.
class A{
void m1(){
System.out.println("m1-A");
}
class B extends A{
void m2(){
System.out.println("m2-B");
}
}
}
public class Main {
public static void main(String[] args){
A a = new A();
a.m1();
A.B ab = a.new B();
ab.m1();
ab.m2();
}
}
m1-A
m1-A
m2-B
Q) Is it possible to declare an abstract class inside a class?
Yes, it is possible to declare an abstract class inside a class but the subclass of the respective abstract class must be provided in the same outer class.
class A {
// abstract class inside another class
abstract class B{
void m1(){
System.out.println("m1-B");
}
abstract void m2();
abstract void m3();
}
class C extends B{
void m2(){
System.out.println("m2-C");
}
void m3(){
System.out.println("m3-C");
}
}
}
public class Main {
public static void main(String[] args){
A.B ab = new A().new C();
ab.m1();
ab.m2();
ab.m3();
}
}
m1-B
m2-C
m3-C
Q) Is it possible to declare an interface inside a class?
Yes, it is possible to declare an interface inside a class but the implementation class of the respective interface must be provided within the same outer class.
class A{
interface I{
void m1();
void m2();
void m3();
}
class B implements I{
public void m1(){
System.out.println("m1-B");
}
public void m2(){
System.out.println("m2-B");
}
public void m3(){
System.out.println("m3-B");
}
}
}
public class Main {
public static void main(String[] args){
A.I ai = new A().new B();
ai.m1();
ai.m2();
ai.m3();
}
}
m1-B
m2-B
m3-B
Q) Is it possible to declare a class inside an abstract class?
Yes, it is possible to declare a class inside an abstract class but we must take a subclass for the abstract class and create an object for the subclass in place of the abstract class while creating an object for the inner class.
abstract class A{
class B{
void m1(){
System.out.println("m1-B");
}
void m2(){
System.out.println("m2-B");
}
void m3(){
System.out.println("m3-B");
}
}
}
class C extends A{
// Now Class B is an inner class to class C
}
public class Main {
public static void main(String[] args){
A.B ab = new C().new B();
ab.m1();
ab.m2();
ab.m3();
}
}
m1-B
m2-B
m3-B
Q)Is it possible to declare an abstract class inside another abstract class?
Yes, it is possible to declare an abstract class inside another abstract class, but we must provide the subclass for the inner abstract class either inside the same outer abstract class or inside the subclass of the outer abstract class.
abstract class A{
abstract class B{
void m1(){
System.out.println("m1-B");
}
abstract void m2();
abstract void m3();
}
class C extends B{
void m2(){
System.out.println("m2-C");
}
void m3(){
System.out.println("m3-C");
}
}
}
class D extends A{
// abstract class B and class C are inner class to class D
}
public class Main {
public static void main(String[] args){
A.B ab = new D().new C();
ab.m1();
ab.m2();
ab.m3();
}
}
m1-B
m2-C
m3-C
abstract class A{
abstract class B{
void m1(){
System.out.println("m1-B");
}
abstract void m2();
abstract void m3();
}
}
class D extends A{
class C extends B{
void m2(){
System.out.println("m2-C");
}
void m3(){
System.out.println("m3-C");
}
}
}
public class Main {
public static void main(String[] args){
A.B ab = new D().new C();
ab.m1();
ab.m2();
ab.m3();
}
}
m1-B
m2-C
m3-C
Q) Is it possible to declare an interface inside an abstract class?
Yes, It is possible to declare an interface inside an abstract class , but we can provide an implementation class for the inner interface either in the same outer abstract class or in the subclass of the outer abstract class.
abstract class A{
interface I{ //A.I ai
void m1();
void m2();
void m3();
}
class B implements I{
public void m1(){
System.out.println("m1-B");
}
public void m2(){
System.out.println("m2-B");
}
public void m3(){
System.out.println("m3-B");
}
}
}
class C extends A{
//interface I and its implementation class B are the inner classes inside class C
}
public class Main {
public static void main(String[] args){
A.I ai = new C().new B();
ai.m1();
ai.m2();
ai.m3();
}
}
m1-B
m2-B
m3-B
abstract class A{
interface I{ //A.I ai
void m1();
void m2();
void m3();
}
}
class C extends A{
class B implements I{
public void m1(){
System.out.println("m1-B");
}
public void m2(){
System.out.println("m2-B");
}
public void m3(){
System.out.println("m3-B");
}
}
}
public class Main {
public static void main(String[] args){
A.I ai = new C().new B();
ai.m1();
ai.m2();
ai.m3();
}
}
m1-B
m2-B
m3-B
Static Inner Classes
Declaring a static class inside a class is called a Static Inner class.
class Outer{
static class Inner{
—-----
}
}
If we declare variables and methods inside a static inner class and if we want to access members of the static inner class then we have to create an object for the static inner class.
Outer.Inner refVar = new Outer.Inner();
Static inner classes are able to allow only static members of the outer classes directly, they will not allow instance members of the outer classes. Static inner classes are able to allow static declarations directly in all versions of the java.
class A{
int x = 10;
static int y = 20;
static class B{
int i = 10;
static int k = 30;
void m1(){
System.out.println("m1-A");
//System.out.println(x); ---> Error
System.out.println(y);
System.out.println(k);
}
}
}
public class Main {
public static void main(String[] args){
A.B ab = new A.B();
System.out.println(ab.i);
ab.m1();
}
}
10
m1-A
20
30
Q)Is it possible to declare a class inside an interface?
Yes, it is possible to declare a class inside an interface, in this case the provided inner class is by default a static inner class, here we can access the members of the inner class as like a static inner class.
interface I{
class A{ // by default : static inner class
void m1(){
System.out.println("m1-A");
}
void m2(){
System.out.println("m2-A");
}
void m3(){
System.out.println("m3-A");
}
}
}
public class Main {
public static void main(String[] args){
I.A ia = new I.A();
ia.m1();
ia.m2();
ia.m3();
}
}
m1-A
m2-A
m3-A
Q)Is it possible to declare an abstract class inside an interface?
Yes, it is possible to declare an abstract class inside an interface, but we must provide a subclass for the abstract class inside the same outer interface, here the provided subclass is by default a static inner class, so we can access members of the abstract class by creating object for the static inner class.
interface I{
abstract class A{
void m1(){
System.out.println("m1-A");
}
abstract void m2();
abstract void m3();
}
class B extends A{// static class B
void m2(){
System.out.println("m2-B");
}
void m3(){
System.out.println("m3-B");
}
}
}
public class Main {
public static void main(String[] args){
I.A ia = new I.B();
ia.m1();
ia.m2();
ia.m3();
}
}
m1-A
m2-B
m3-B
Q)Is it possible to have an interface inside an interface?
Yes, it is possible to declare an interface inside the another interface, but we must provide an implementation class for the inner interface inside the same outer interface, in this case the provided implementation class is by default a static inner class, here we can access the members of the inner interface by creating object for the static inner class.
interface I1{
interface I2{
void m1();
void m2();
void m3();
}
class A implements I2{// static inner class
public void m1(){
System.out.println("m1-A");
}
public void m2(){
System.out.println("m2-A");
}
public void m3(){
System.out.println("m3-A");
}
}
}
public class Main {
public static void main(String[] args){
I1.I2 i12 = new I1.A();
i12.m1();
i12.m2();
i12.m3();
}
}
m1-A
m2-A
m3-A
Method Local Inner Class
Declaring a class inside a method is called a Method Local Inner Class.
If we declare a class inside a method then that inner class will have the scope up to the respective method only, we have to create an object for the inner class inside the outer method only , we have to access the inner class members inside the outer method only.
class A{
void m1(){
class B{
void m2(){
System.out.println("m2-B");
}
void m3(){
System.out.println("m3-B");
}
}
B b = new B();
b.m2();
b.m3();
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.m1();
}
}
In Java applications, it is possible to declare an abstract class inside a method, but we must provide the respective subclass of the abstract class inside the same outer method.
class A{
void m1(){
abstract class B{
void m2(){
System.out.println("m1-B");
}
abstract void m3();
abstract void m4();
}
class C extends B{
void m3(){
System.out.println("m2-C");
}
void m4(){
System.out.println("m3-C");
}
}
B b = new C();
b.m2();
b.m3();
b.m4();
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.m1();
}
}
m1-B
m2-C
m3-C
IN Java applications, it is possible to declare an interface inside a method, but the implementation class of the interface must be provided in the same outer method.
class A{
void m1(){
interface I{
void m2();
void m3();
void m4();
}
class B implements I{
public void m2(){
System.out.println("m2-B");
}
public void m3(){
System.out.println("m3-B");
}
public void m4(){
System.out.println("m4-B");
}
}
I i = new B();
i.m2();
i.m3();
i.m4();
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
a.m1();
}
}
m2-B
m3-B
m4-B
Anonymous inner class
Anonymous inner class is a nameless inner class, it can be used to provide either implementation or overriding for the methods of the classes, abstract classes and interfaces without taking subclasses or implementation classes.
Why we need ?
Simple interface example :
Simple class example :
In all above cases, when we want to override a method, 2 possibilities, we have to either implement an interface or extend a class and provide a new implementation.
Q) What if we intend to use that implementation only once? Creating a new class is not that much necessary. We need to manage that class.
One-time use : When you need a class for a specific task and don’t intend to reuse it elsewhere, anonymous classes are a convenient way to define the class where it’s needed.
When the class’s purpose is simple, such as a short piece of code to perform a specific task, using an anonymous class can make the code more readable by keeping the implementation close to where it’s used.
Interface/Abstract class implementation: They are often used to implement interfaces or extend abstract classes with a specific implementation in a single place, without the need to create a separate named class.
Syntax
Anonymous classes – you create an object using a new keyword and then provide class definition by using braces { } .
Class/Abstactclass/Interface refVar = new Class/AbstractClass/Interface() {
—-implementation to all methods—----
};
When you want to override a method and use that functionality only once, instead of creating a new class and providing that functionality, we can use anonymous and write that logic just at the place where it is required.
List<Item> items = new ArrayList<>();
// Adding some sample items
items.add(new Item("Laptop", 1000));
items.add(new Item("Smartphone", 500));
items.add(new Item("Tablet", 300));
// Sorting items by name using an anonymous class
Collections.sort(items, new Comparator<Item>() {
@Override
public int compare(Item item1, Item item2) {
return item1.getName().compareTo(item2.getName());
}
});
Note: in general, we will use anonymous inner classes for the abstract classes and interfaces in order to avoid the subclass and implementation classes.
When you just want to provide an overriding implementation and use that only once, then go with anonymous inner classes.
Anonymous inner classes are particularly useful when you need to create a one-time-use class that implements an interface or extends a class without defining a separate named class for that purpose. They are often used for event handling, callbacks, and other situations where a small, temporary class is needed.
With interfaces
// Greeting interface
interface Greeting {
void greet();
}
public class AnonymousInnerClassExample {
public static void main(String[] args) {
// Creating an instance of an anonymous inner class
Greeting greeter = new Greeting() {
@Override
public void greet() {
System.out.println("Hello from an anonymous inner class!");
}
};
// Calling the greet method of the anonymous inner class
greeter.greet();
}
}
Overriding class behavior
Here, we are providing new behavior to show() method without creating a new class and it is used only once.
class P {
void show() {
System.out.println("in P show");
}
}
public class Demo {
public static void main(String[] args) {
P obj = new P() {
@Override
public void show() {
System.out.println("from anonymous inner class");
}
};
obj.show(); // from anonymous inner class
}
}
With Abstract classes
We need to implement all abstract methods in anonymous inner class.
Using anonymous inner class with interfaces
interface Mobile {
void call();
void message();
}
public class Demo {
public static void main(String[] args) {
Mobile obj = new Mobile() {
@Override
public void call() {
System.out.println("Calling");
}
@Override
public void message() {
System.out.println("Sent message");
}
};
obj.call();
obj.message();
}
}
Examples
EX: Example Before Anonymous inner class
interface I{
void m1();
void m2();
void m3();
}
class A implements I{
public void m1(){
System.out.println("m1-A");
}
public void m2(){
System.out.println("m2-A");
}
public void m3(){
System.out.println("m3-A");
}
}
public class Main {
public static void main(String[] args) {
I i = new A();
i.m1();
i.m2();
i.m3();
}
}
Example program – After Anonymous Inner Class
interface I{
void m1();
void m2();
void m3();
}
public class Main {
public static void main(String[] args) {
I i = new I(){
public void m1(){
System.out.println("m1-AIC");
}
public void m2(){
System.out.println("m2-AIC");
}
public void m3(){
System.out.println("m3-AIC");
}
};
i.m1();
i.m2();
i.m3();
}
}
EX2:
abstract class A{
void m1(){
System.out.println("m1-A");
}
abstract void m2();
abstract void m3();
}
public class Main {
public static void main(String[] args) {
A a = new A(){
void m2(){
System.out.println("m2-AIC");
}
void m3(){
System.out.println("m3-AIC");
}
};
a.m1();
a.m2();
a.m3();
}
}
m1-A
m2-AIC
m3-AIC
EX3:
public class Main {
public static void main(String[] args) {
Object object = new Object(){
@Override
public String toString() {
return "Raghu Software Solutions";
}
};
System.out.println(object);
}
}
Raghu Software Solutions
Static Anonymous Inner class
In Java applications, we are able to declare static anonymous inner classes just by providing a static keyword before the anonymous inner class declaration.
class Test{
static Object obj = new Object(){
{
System.out.println("Welcome To Java learning.");
System.exit(0);
}
};
}
D:\Fullstack10AM>javac Test.java
D:\Fullstack10AM>java Test
Welcome To Java learning.
In Java applications, we are able to pass an anonymous inner class as a parameter to the methods.
Before Anonymous Inner classes :
interface Vehicle{
void drive();
}
class Bike implements Vehicle{
public void drive(){
System.out.println("Driving Bike....");
}
}
class Car implements Vehicle{
public void drive(){
System.out.println("Driving Car......");
}
}
class Bus implements Vehicle{
public void drive(){
System.out.println("Driving Bus....");
}
}
class Driver{
public void driveCar(Vehicle car){
car.drive();
}
public void driveBus(Vehicle bus){
bus.drive();
}
public void driveBike(Vehicle bike){
bike.drive();
}
}
public class Main {
public static void main(String[] args) {
Driver driver = new Driver();
Vehicle bike = new Bike();
Vehicle car = new Car();
Vehicle bus = new Bus();
driver.driveBike(bike);
driver.driveCar(car);
driver.driveBus(bus);
}
}
Driving Bike....
Driving Car......
Driving Bus....
After Anonymous Inner Classes :
interface Vehicle{
void drive();
}
class Driver{
public void driveBike(Vehicle bike){
bike.drive();
}
public void driveCar(Vehicle car){
car.drive();
}
public void driveBus(Vehicle bus){
bus.drive();
}
}
public class Main {
public static void main(String[] args) {
Driver driver = new Driver();
driver.driveBike(new Vehicle() {
@Override
public void drive() {
System.out.println("Driving Bike.....");
}
});
driver.driveCar(new Vehicle(){
public void drive(){
System.out.println("Driving Car.....");
}
});
driver.driveBus(new Vehicle() {
@Override
public void drive() {
System.out.println("Driving Bus.....");
}
});
}
}
Driving Bike.....
Driving Car.....
Driving Bus.....
Note: In Java applications, Anonymous inner classes are suggestible when we have less number of methods inside the interfaces, if we have more methods inside the interfaces then anonymous inner classes are not suggestible, where the implementation classes are suggestible.