• In Java we have an option to declare a class inside another class or any local context, this class is called Inner class.
• Generally, we use inner class to develop a module or category which is dedicated to another category.
class SavingAccount{
void apply(){
Loan l1 = new Loan();
}
}
class Loan{
}
class CurrentAccount{
void apply(){
Loan l2 = new Loan();
}
}
In this example we are developing a banking module that requires to establish that only Savings Account holders are eligible to apply for loans. Here, we can see that we have three different classes which are representing Savings Account, Current Account and Loan categories. In this example Loan is a simple class and we can create an object of Loan class from SavingsAccount as well as CurrentAccount classes. However, this is not what is actually required. As per the business logic only Savings Account holder can apply for loan. This means Loan class has to be totally dedicated to the SavingAccount class and using Inner class concept we can easily achieve this purpose.
class SavingAccount{
class Loan{
}
void apply(){
Loan l1 = new Loan();
}
}
class CurrentAccount{
void apply(){
// Loan l2 = new Loan(); :- error
}
}
In this example we are using the Inner Class concept, as we can see here Loan class is an Inner class of SavingsAccount class, so only from SavingsAccount class we are able to create an object of Loan class.
• After the successful compilation we get .class file for inner class as well.
class Outer{
class Inner{
}
}
In this example we have a class, which is Outer, and inside the Outer class we have declared an Inner class so that after successful compilation we get two .class files which are Outer.class and Outer$Inner.class files.
Types of Inner class: -
1. Non-Static Inner class (Instance Inner class)
2. Static Inner class
3. Method Local Inner class
4. Anonymous Inner class
• When we declare a class inside another class without static modifier, we call it non-static inner class.
• Since an instance inner class is an instance member of outer class therefore we have to create an object of outer class and only with that outer class object we can create an object of an instance inner class.
• We can define an non-static inner class as a private class.
• We can access all the members of outer class from instance inner class directly.
• We cannot access a member of instance inner class from outer class directly, if we attempt to do so we will get an error at the time of compilation.
• To access instance inner class member from outer class we first have to create inner class object.
class JTC{
public static void main(String arg[]){
System.out.println("----Main in JTC class----");
A a1 = new A();
a1.show();
A.B b1 = a1.new B();
b1.m1();
// A.C c1 = a1.new C(); --> error
}
}
class A{
int a = 10;
static int b = 20;
class B{
void m1(){
System.out.println("m1 in A.B class");
System.out.println("a :- "+a);
System.out.println("b :- "+b);
}
}
private class C{
void m2(){
System.out.println("m2 in A.C class");
System.out.println("a :- "+a);
System.out.println("b :- "+b);
}
}
void show(){
System.out.println("show in A class");
// m1(); --> error
// m2(); --> error
B b1 = new B();
b1.m1();
C c1 = new C();
c1.m2();
}
}
----Main in JTC class---- show in A class m1 in A.B class a :- 10 b :- 20 m2 in A.C class a :- 10 b :- 20 m1 in A.B class a :- 10 b :- 20
In the above example we have class A in which we have an instance variable int a = 10, a static variable static int b = 20, an instance inner class B in which we have void m1(), a private instance inner class C having void m2(), and finally we have an instance method show() in A class.
We can see that from void m1() of class B we are accessing the values of int a = 10 and static int b = 20 and we are accessing these same values from void m2() of C class; this shows that we can directly access instance and static member of outer class from instance inner class or non-static inner class.
In void show() method of outer class, which is class A, we are creating an object of class B and class C and along with that object we are invoking m1() and m2() methods respectively.
In the last section we have JTC class in which we have a main method where we are creating an object of A.B class using the object of class A; however, as we can see, we are not able to create any object of A.C class from JTC class because class C is a private inner class and private members are not visible to outsiders.
• When we declare a class inside another class with static modifier, we call the class static inner class.
• We can create an object of static inner class directly from the outer class, here there is no need to create an object of outer class first.
• We can directly access only a static member of the outer class from static inner class, because static inner class also works on early binding concept like other static members.
• In order to access instance members of outer class from static inner class we need to create an object of outer class first and along with that object we can access instance member.
class JTC{
public static void main(String arg[]){
A.B obj = new A.B();
obj.show();
System.out.println("test :- "+A.B.test);
}
}
class A{
int a = 10;
static int b = 20;
static class B{
static int test = 200;
void show(){
System.out.println("show in A.B class");
// System.out.println("a :- "+a); --> error
System.out.println("b :- "+b);
System.out.println("a :- "+new A().a);
}
}
}
show in A.B class b :- 20 a :- 10 test :- 200
In the above program we can see that we have class A and inside the A class we have declared certain members, which are: int a = 10, static int b = 20 and a static inner class B.
In static inner class B we have a static variable i.e., static int test = 200, and one instance method i.e., void show ().
We can see that in JTC class we are creating an object of A.B class; but we should note that unlike as in the case of instance inner class, here we are still able to access member of A.B class without creating an object of static inner class.
• In Java we can declare a class inside a local context, and as like in method, inside a block or a constructor as well.
• When we declare a class in a local context then we cannot access that class from outside that local context.
• We can directly access all the members of outer class from the Method Local inner class.
• In order to access any Local Inner class member from its local context we have to use an object of Method Local Inner class.
class JTC{
public static void main(String arg[]){
Outer obj = new Outer();
obj.m1();
}
}
class Outer{
int a = 10;
static int b = 20;
void m1(){
int c = 30;
System.out.println("m1 in Outer class");
class Inner{
int d = 40;
void m2(){
int e = 50;
System.out.println("m2 in Outer.Inner class");
System.out.println("a :- "+a);
System.out.println("b :- "+b);
System.out.println("c :- "+c);
System.out.println("d :- "+d);
System.out.println("e :- "+e);
}
}
Inner i1 = new Inner();
i1.m2();
}// m1 close.
void m3(){
System.out.println("m3 in A Outer class");
// Inner i1 = new Inner(); :- error
}
}
m1 in Outer class m2 in Outer.Inner class a :- 10 b :- 20 c :- 30 d :- 40 e :- 50
In this example we have shown Method Local Inner Class. As you can see that in the Outer class we have an Instance method which is void m1 () and in this method we have a Method Local Inner Class which is an Inner class and inside that Inner class we have a method void m2 () and from which we have accessed Outer class members: (int a = 10, static int b = 20), local variable of m1() (int c = 30), Instance variable (int d = 40) of Inner class and local variable (int e = 50) of m2() itself. As we can see that in void m3() method, which is a different method of Outer class, we are trying to create an object of Method Local Inner class; but as we have discussed earlier, we can’t access a method local inner class from outside its local context, and that is the reason we get an error in this line.
In Java an Anonymous Inner class is a special class with certain special features. Before we work with an Anonymous Inner class, we have to bear few important points in our minds.
• An Anonymous Inner class does not have any naming convention.
• An Anonymous Inner class is an object of itself.
• We cannot create an object of an Anonymous Inner class explicitly, like we do in concrete classes.
• An Anonymous Inner class will always be the sub class of an Interface or an Abstract class or a Concrete Class.
class JTC{
public static void main(String arg[]){
A a1 = new A(){
void m1(){
System.out.println("m1 in JTC$1 class");
}
};
a1.m1();
}
}
abstract class A{
abstract void m1();
}
m1 in JTC$1 class
This example helps us to understand that how we can create an Anonymous Inner class and its uses. In the above example we can see that we have an abstract class A that has an Abstract method void m1(), and in JTC class we have a main method in which we are creating an Anonymous Inner class which is the sub class of A; here we are overriding void m1().
new A(){
void m1(){
System.out.println("m1 in JTC$1 class");
}
};
As we know an Anonymous inner class is an object of itself so we are storing its reference into A type reference variable which is A a1;
A a1 = new A(){
void m1(){
System.out.println("m1 in JTC$1 class");
}
};
Here we are using Dynamic Dispatch concept and finally we are invoking m1().