Inner Class Java

A class declared inside another class or interface in Java is called Java inner class or nested class. To logically group classes and interfaces in one place Java inner class is used. It thus makes it more readable and maintainable. All the members of the outer class can be accessed by an inner class including private data members and methods.

Java inner class syntax:

class Java_Outer_class{  
 //code to execute 
 class Java_Inner_class{  
  //code to execute
 }  
}  

 

Java inner class advantages:

Java inner class holds three major advantages. These are:

  • It depicts a special type of relationship, i.e., all the members of the outer class can be accessed by an inner class including private data members and methods.
  • It develops a more readable and maintainable code, i.e, an inner class logically group classes and interfaces in one place.
  • It facilitates Code Optimization, i.e, an inner class requires less code to write.

Difference between Java nested class and Java inner class:

Not all nested classes is an inner class, i.e, only the non-static nested classes are known as inner classes. However, an inner class is a part of the nested class.

Types of Nested classes:

A nested class in Java can either be a non-static or static nested class, where the non-static nested class is known as an inner class.

  • Non-static nested class or inner class
    1. Member inner class
    2. Anonymous inner class
    3. Local inner class
  • Static nested class
Type Description
Member Inner Class Created within a class and an outside method.
Anonymous Inner Class Created for implementing an interface or extending class. The name of an anonymous inner class is decided by the java compiler itself.
Local Inner Class Created within a method.
Static Nested Class Created within a class.
Nested Interface The interface created within a class or an interface.

Java Member inner class

An inner class created inside a class but outside a method in Java is called a Java member inner class.


Syntax:

class Outer{  
 //code to execute 
 class Inner{  
  //code to execute
 }  
}  

 

Example:

class TestMemberOuter1{
 private int num=16;
 class Inner{
  void number(){System.out.println("Number is "+num);}
 }
 
 void display(){
  Inner in=new Inner();
  in.number();
 }
 public static void main(String args[]){
  TestMemberOuter1 obj=new TestMemberOuter1();
  obj.display();
 }
}

Output:

Number is 16

 

Explanation:

In the above example, the number() method is created in the member inner class. Here, the private data member of the outer class is being accessed by this method.

Internal working of Java member inner class:

In the case of an inner class, two class files are created by the java compiler. For the inner class, the class file name is “Outer$Inner”. The instance of the outer class needs to be created to instantiate the inner class. Inside the instance of the outer class, an instance of the inner class is created.

Internal code generated by the compiler:

A class file named Outer$Inner is created by the java compiler. The Member inner class can access all the data members of the Outer class including private because it has the reference of Outer class.

Code:

import java.io.PrintStream;  
class Outer$Inner  
{  
    final Outer this$0;  
    Outer$Inner()  
    { super();  
        this$0 = Outer.this;  
    }  
    void number()  
    {  
        System.out.println((new StringBuilder()).append("Number is ")  
                    .append(Outer.access$000(Outer.this)).toString());  
    }  
}  

 

Java Anonymous inner class

In Java, a class with no name is known as Java anonymous inner class. To override a method of a class or interface in Java, the anonymous inner class is used. There are two ways to create an anonymous inner class:

  • Class (may be abstract or concrete).
  • Interface

Example 1: Java Anonymous inner class using the class:

abstract class Tom{
  abstract void health();
}

class TestAnnonymousInner{
 public static void main(String args[]){
  Tom t=new Tom(){
  void health(){System.out.println("Daily Exercise");}
  };

  t.health();
 }
}

Output:

Daily Exercise

Internal working:

Tom t=new Tom(){
void health(){System.out.println("Daily Exercise");}
};

In the above code, a class is created whose name is decided by the compiler. It extends the Tom class and facilitates the implementation of the health() method. Here, the ‘t’ reference variable of Tom type, is used to refer to the created object of Anonymous class.

The internal class generated by the compiler:

import java.io.PrintStream;  
static class TestAnonymousInner$1 extends Tom 
{  
   TestAnonymousInner$1(){}  
   void health()  
    {  
        System.out.println("Daily Exercise");
    }  
}  

Example 2: Java Anonymous inner class using an interface:

interface Healthy{
 void health();
}

class TestAnnonymousInner1{
 public static void main(String args[]){
 
 Healthy h=new Healthy(){
  public void health(){System.out.println("Daily Exercise");}
 };
 h.health();
 }
}

Output:

Daily Exercise

Internal working:

Healthy h=new Healthy(){
  public void health(){System.out.println("Daily Exercise");}
 }; 

In the above code, a class is created whose name is decided by the compiler. It implements the Healthy interface and facilitates the implementation of the health() method. Here, the ‘h’ reference variable of Healthy type, is used to refer to the created object of Anonymous class.

The internal class generated by the compiler:

import java.io.PrintStream;  
static class TestAnonymousInner1$1 implements Healthy  
{  
TestAnonymousInner1$1(){}  
void health(){System.out.println("Daily Exercise");}  
}  

Java Local inner class

In Java, a class created inside a method is called Java local inner class. To invoke the methods of local inner class, this class must be instantiated inside the method.

Example:

public class localInner1{
 private int num=16;//instance variable
 void display(){
  class Local{
   void number(){System.out.println(num);}
  }
  Local n=new Local();
  n.number();
 }
 public static void main(String args[]){
  localInner1 obj=new localInner1();
  obj.display();
 }
}

Output:

16

Internal class generated by the compiler:

A class named Simple$1Local with the reference of the outer class is created by the compiler.

Code:

import java.io.PrintStream;  
class localInner1$Local  
{  
    final localInner1 this$0;  
    localInner1$Local()  
    {     
        super();  
        this$0 = Simple.this;  
    }  
    void number()  
    {  
        System.out.println(localInner1.access$000(localInner1.this));  
    }  
}  

Rules:

  • The local variable cannot be private, public or protected.
  • We can’t invoke the Local inner class from outside the method.
  • The non-final local variable cannot be accessed by the Local inner class till JDK 1.7. The access of the non-final local variable in the local inner class is possible since JDK 1.8.

Example: Local inner class with local variable:

class localInner2{
 private int num1=16;//instance variable
 void display(){
  int num2=95;//local variable must be final
  class Local{
   void number(){System.out.println(num2);}//C.T.Error
  }
  Local n=new Local();
  n.number();
 }
 public static void main(String args[]){
  localInner2 obj=new localInner2();
  obj.display();
 }
}

Output:

95

Java static nested class

In Java, a static class created inside a class is called a Java static nested class.

  • Can be accessed by outer class name.
  • Cannot access non-static data members and methods.
  • Can access static data members of outer class including private.
  • Cannot access non-static (instance) data members or methods.

Example: Java static nested class with instance method:

class TestOuter1{
  static int num=16;

  static class Inner{
   void number(){System.out.println("Number is "+num);}
  }
 
  public static void main(String args[]){
  TestOuter1.Inner obj=new TestOuter1.Inner();
  obj.number();
  }
}

Output:

Number is 16

Explanation:

In the above example, the instance of the static nested class must be created as it has an instance method number(). But since the nested class is static and static properties, there is no need to create the object of Outer class. Thus, here the methods or classes can be accessed without an object.

Internal class generated by the compiler:

import java.io.PrintStream;  
static class TestOuter1$Inner  
{  
TestOuter1$Inner(){}  
void number(){  
System.out.println((new StringBuilder()).append("Number is ")  
.append(TestOuter1.num).toString());  
}    
}  

Example: Java static nested class with a static method:

class TestOuter2{
  static int num=16;

  static class Inner{
   static void number(){System.out.println("Number is "+num);}
  }
 
  public static void main(String args[]){
  TestOuter2.Inner.number();//no need to create the instance of static nested class
  }
}

Output:

Number is 16

Explanation:

There is no need to create an instance of the static nested class when the static member is present inside the static nested class.

Java Nested Interface

In Java, a nested interface is an interface that is declared within another interface or class. To group related interfaces for easy maintenance, the Java nested interface is used. The outer interface or class must refer to a Java nested interface, as it cannot be accessed directly.

Rules for nested interfaces:

  • When declared inside the interface, the Java Nested interface must be public.
  • When declared within the class, the Java Nested interface can have any access modifier.
  • They are declared static implicitly.

Syntax: Nested interface declared within the interface:

interface interface_name{  
 ...  
 interface nested_interface_name{  
  ...  
 }  
}   

Syntax: Nested interface declared within the class:

class class_name{  
 ...  
 interface nested_interface_name{  
  ...  
 }  
}   

Example: Nested interface declared within the interface:

interface ABC{
  void display();
  interface XYZ{
   void message();
  }
}

class TestNestedInterface1 implements ABC.XYZ{
 public void message(){System.out.println("Hello World!!");}

 public static void main(String args[]){
  ABC.XYZ xyz=new TestNestedInterface1();//upcasting here
  xyz.message();
 }
}

Output:

Hello World!!

Explanation:

In the above example, we are demonstrating the declaration and the access of the nested interface. Here, the XYZ interface cannot be accessed directly, so we are accessing it by its outer interface ABC.

Internal code generated by the java compiler:

The public and the static interface is internally created by the java compiler.

Code:

public static interface ABC$XYZ  
{  
  public abstract void message();  
}  

Example: Nested interface declared within the class:

class ABC{
  interface Msg{
   void message();
  }
}

class TestNestedInterface2 implements ABC.Msg{
 public void message(){System.out.println("Hello World!!");}

 public static void main(String args[]){
  ABC.Msg msg=new TestNestedInterface2();//upcasting here
  msg.message();
 }
}

Output:

Hello World!!

Explanation:

In the above example, we are demonstrating the way to define an interface inside the class and the way to access it.

To define a class inside the interface:

The Java compiler creates a static nested class when a class is defined inside the interface.

Code:

interface M{  
  class A{}  
}