2 min read

Inner Classes in Java

Inner classes are non-static classes defined inside of another class.
Inner Classes in Java

What is an Inner Class?

Non-static nested classes are referred to as inner classes. An inner class is a non-static class that is defined inside another class. They follow most of the same rules as normal classes. They can have constructors, methods, variables, etc. just like a normal class. Inner classes can be marked with any access modifier. The following code defines a class named OuterClass and an inner class named InnerClass.

public class OuterClass {

    private class InnerClass {
    
    }
}

Methods and Variables

Both outer and inner classes have access to each other's variables and methods. If an inner class has something marked as private, it is still accessible to the outer class.

public class OuterClass {
    private int x = 3;

    public void innerExample() {
        final var inner = new InnerClass();
        inner.y = 10;
    }

    public class InnerClass {
        private int y = 8;

        public void print() {
            System.out.println(x);
        }
    }
}

In the method innerExample(), an instance of InnerClass is created, and then the variable y is assigned a value. Inside the print() method, variable x is printed. Both of these methods show how inner and outer classes can use each other's variables. This applies to methods as well.

Using The this Keyword

Using the this keyword works the same as any other class. If you are in the outer class, this refers to the outer class. If you are in the inner class, this refers to the inner class. Using this is redundant unless there is a naming conflict. If you had a naming conflict in your inner class, you can still use the this keyword and access what you are wanting to, but it is written differently depending on which class you are referencing.

public class OuterClass{
    private int x = 10;

    public class InnerClass {
        private int x = 20;
        
        public void print() {
            System.out.println("Outer Class: " + OuterClass.this.x);
            System.out.println("Inner Class: " + this.x);
        }
    }
}

This shows how to access both x variables in an inner class using the this keyword. Using the this keyword will prevent shadowing that can occur when the same name is used in both the inner and outer class.

Instantiating Inner Classes

Creating instances of an inner class is the same as any other class if you are creating them inside the class they are in.

public class OuterClass {

    public void method() {
        final var inner = new InnerClass();
    }

    public class InnerClass {
    }
}

If a class inherits a class that has an inner class, instantiating them is also the same as a normal class.

public class OuterClass {

    public class InnerClass {
    }
}

public class AnotherOuterClass extends OuterClass {
    private final InnerClass inner = new InnerClass();
}

If you are creating an instance of an inner class outside of the outer class, the syntax is a little different. Inner classes have to be associated with an outer class instance. You cannot create an instance of an inner class without an outer class instance. In the examples above, the inner class instances are created inside of an outer class, so they are already tied to an instance of that outer class. To instantiate an inner class outside an outer class, you must first create an instance of the outer class. With the instance of the outer class, you can create instances of the inner class with the following:

public class MyClass {

    public void method() {
        final OuterClass outer = new OuterClass();
        final OuterClass.InnerClass inner = outer.new InnerClass();
    }
}

Conclusion

Inner classes are non-static classes defined inside of another class. They should only be used when the inner class is only used in the class it is defined in. Inner record classes are usually a better option but this can change depending on your use case.