Java Inner Class

If an object contains another object, then this means that a class includes another class. For example, the relationship between cars and engines. In this case, the engine class is called an inner class. In this post, I will explore the properties of three types of inner classes (Member Inner Class / Local Inner Class / Anonymous Inner Class).

In Java, inner class can include:

1: Member Inner Class

2: Local Inner Class (Include Anonymous Inner Class)

2.5: Anonymous Inner Class


1: Member Inner Class

// Outer class
public class Body {
    // Inner class
    public class Heart {
        public void beat() {
            // Method of inner class
            System.out.println("Heart beats!");
            // Correct! Inner class can access methods of outer class
            System.out.println("My name is: " + getName());
        }
    }

    // Method of outer class
    public void methodBody() {
        System.out.println("Method of outer class");
    }

    // Member variable of outer class
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Two ways of using inner class

1: Indirect way: We can use the method of outer class to create an inner class object.

// Method of outer class
public void methodBody() {
    Heart heart = new Heart();
    heart.beat();
}

// Main method
public static void main(String[] args) {
    Body body = new Body();
    body.methodBody(); // Use outer class object method to indirectly invoke inner class object method
}

2: Direct way: OuterClass.InnerClass obj = new OuterClass().new InnerClass();

// Main method
public static void main(String[] args) {
    Body.Heart heart = new Body().new Heart();
    heart.beat();
}

How to access variables with same names of outer and inner classes:

public class Outer {
    int num = 10;
    public class Inner extends Object {
        int num = 20;
        public void methodInner() {
            int num = 30;
            // Access local variable of inner class
            System.out.println(num); // 30
            // Access member variable of inner class
            System.out.println(this.num); // 20
            // Access member variable of outer class
            System.out.println(Outer.this.num); // 10
        }
    }
}

2: Local Inner Class

If a class is defined inside of a method, then the class is called local inner class.

public class Outer {
    public void methodOuter() {
        class Inner {
            int num = 10;
            public void methodInner() {
                System.out.println(num);
            }
        }
        Inner inner = new Inner();
        inner.methodInner();
    }
}

public class DemoMain {
    public static void main(String[] args) {
        Outer obj = new Outer();
        obj.methodOuter();
    }
}

Summary of modifiers for class ( public > protected > (default) > private )

  • Normal Class: public / (default)
    • There is no class outside of normal classes.
  • Member Inner Class: public / protected / (default) / private
    • Since this is a member.
  • Local Inner Class: We do not put anything. (Leave it empty)
    • Only the outer method can access it.
    • Putting no modifier is different from using (default) because other classes in the same package also can not access this inner class.

‘Final’ issue of the local inner class

If a local inner class wants to access the local variable of its outer method, the local variable must be ‘final’.

Explanation: We store the object that is new-ed in the heap and store the local variable in the stack. When the method finishes, the local variable inside of that will disappear. However, the local inner class object is still in the heap until it is automatically recycled by Java. Therefore, we need to store the local variable that is used by the object. Hence, we should put ‘final’ keyword to make the local variable as a constant.

public class MyOuter {
    public void methodOuter() {
        // From Java 8+, as long as the local variable does not change, then we can omit the 'final' keyword.
        final int num = 10; // local variable
        class MyInner {
            public void methodInner() {
                System.out.println(num);
            }
        }
    }
}

2.5: Anonymous Inner Class

If the implementing class (or derived class) only needs to be used once, then, we can use anonymous inner class.

public class Demo {
    public static void main(String[] args) {
       MyInterface obj = new MyInterface() {
           @Override
           public void method() {
               System.out.println("Anonymous inner class implements methods!");
           }
       };
       obj.method();
    }
}

Properties:

  • {…}; is the contents of the anonymous inner class.
  • Anonymous inner class can only be used once when creating the object.
  • Anonymous object can only be invoked once as well.
new MyInterface() {
    @Override
    public void method() {
        System.out.println("Invoke the method of anonymous object");
    }
}.method();
  • Anonymous inner class omits the implementing class. Anonymous object omits the object name. (They are not the same!)