Inner classes in Java

Inner classes will also called as nested classes. If we define a class inside another class is called as inner or nested class.

Types of inner classes
  1. Inner classes
  2. Local inner class
  3. Static inner class
  4. Anonymous inner class
Inner classes

The inner class is declared inside the another class, which can be coded inside the top level class. Like below


    //Top level class definition
    class OuterClassExample {
        private int myVar = 1;
    
        // inner class definition
        class MyInnerClassDemo {
            public void seeOuter () {
                System.out.println("Value of myVar is :" + myVar);
            }
        } // close inner class definition
    } // close Top level class definition

Inner class acts as a member of the enclosing class and can have any access modifiers: abstract, final, public, protected, private, static. Inner class can access all members of the outer class including those marked private as shown in the above example where inner class is accessing the private variable "myVar" of outer class.

Instantiating an inner class

To instantiate an instance of inner class, there should be a live instance of outer class. An inner class instance can be created only from an outer class instance. An inner class shares a special relationship with an instance of the enclosing class. Instantiating an inner class from within code in outer class:


    class OuterClassExample {
        private int x= 1;
        public void innerInstance()
        {
            MyInnerClassDemo inner = new MyInnerClassDemo();
            inner. seeOuter();
        }
        public static void main(String args[]){
            OuterClassExample obj = new OuterClassExample();
            obj.innerInstance();
        }
        // inner class definition
        class MyInnerClassDemo {
            public void seeOuter () {
                System.out.println("Outer Value of x is :" + x);
            }
        } // close inner class definition	   
        } // close Top level class definition
Instantiating an inner class from outside:

    public static void main(String args[]){
        OuterClassExample.MyInnerClassDemo inner = new OuterClassExample().new MyInnerClassDemo();
        inner.seeOuter();
        }

Local inner class

A method local inner class is defined within a method of the enclosing class. If you want to use inner class, you must instantiate the inner class in the same method, but after the class definition code. Only two modifiers are allowed for method-local inner class which are abstract and final. The inner class can use the local variables of the method (in which it is present), only if they are marked final.


    //Top level class definition
    class MyOuterClassDemo {
        private int x= 1;
    
        public void doThings(){
            String name ="local variable";
            // inner class defined inside a method of outer class
            class MyInnerClassDemo {
            public void seeOuter () {
                System.out.println("Outer Value of x is :" + x);
                System.out.println("Value of name is :" + name);//compilation error!!
            } //close inner class method
            } // close inner class definition
        } //close Top level class method
    } // close Top level class

The above code will throw a compilation error as Inner class cannot use the non-final variables of the method, in which it is defined. This is how it can be fixed: If we mark the variable as final then inner class can use it.


    final String name ="local variable";// inner object can use it
Static inner class

A static nested classes are the inner classes marked with static modifier.Because this is static in nature so this type of inner class doesn’t share any special kind of relationship with an instance of outer class.A static nested class cannot access non static members of outer class.

Example:


    class Outer{
        static class Nested{}
        }

A static nested class can be instantiated like this:


    class Outer{// outer class
        static class Nested{}// static nested class
        }
        
        class Demo{
        public static void main(string[] args){
            // use both class names
            Outer.Nested n= new Outer.Nested();
        }
        }

Consolidated Example:

    public class OuterClass {
        public static void main(String[] args) {
            OuterClass outerClass = new OuterClass();
            outerClass.instantiateInnerClass();
    
            // instantiating an inner class using outer class
            OuterClass.InnerClass obj1 = new OuterClass().new InnerClass();
            obj1.print(); // calling inner class method with the object reference
    
            outerClass.locaMethod(); // calling the method
    
            outerClass.instantiateStaticInnerClass();
        }
    
        public void instantiateInnerClass() {
            InnerClass innerClass = new InnerClass(); // instantiating an inner class
            innerClass.print();
            StaticInnerClass s = new StaticInnerClass();
            s.display();
        }
    
        public static void instantiateStaticInnerClass() {
            StaticInnerClass s = new StaticInnerClass();
            s.display();
        }
        
        // inner class example
        class InnerClass {
            public void print() {
                System.out.println("Print inner class method");
            }
        }
    
        // Locla inner class example
        public void locaMethod() {
            class LocalInnerClass {
                public void localInnerClassMethod() {
                    System.out.println("Local inner class");
                }
            }
            LocalInnerClass localInnerClass = new LocalInnerClass();
            localInnerClass.localInnerClassMethod();
        }
    
        // static inner class
        static class StaticInnerClass {
            public void display() {
                System.out.println("static inner class executed");
            }
        }
    
    }