Java Static Class: A Tutorial on Static Classes in Java

Static classes are basically a way of grouping classes together in Java. Java doesn't allow you to create top-level static classes; only nested (inner) static classes. Let's take a look at an example.

Here's a class called CarParts that declares a static inner class called Wheel.

CarParts.java:

 
public class CarParts {
    
    public static class Wheel {
        public Wheel() {
            System.out.println("Wheel created!");
        }
    }

    public CarParts() {
        System.out.println("Car Parts object created!");
    }
}
 

I've added constructors to both classes so that we can see when they are instantiated -- in other words, when objects are actually created from them.. We can use the CarParts class in the normal way; note that creating a CarParts object does not create a Wheel object.

App.java:

 
public class App {

    public static void main(String[] args) {
        CarParts carParts = new CarParts();
    }

}
 
Car Parts object created!




To instantiate our static class, creating an object from our static Wheel class, we have to use new separately on the class.

App.java:

 
public class App {

    public static void main(String[] args) {
        CarParts.Wheel wheel = new CarParts.Wheel();
    }

}
 
Wheel created!




As you can see, the static inner Wheel class acts like an entirely separate class, which just happens to be accessed via the outer CarParts class. We don't need an instance of the outer class to create an object of a static inner class.

The only exception to static classes acting like completely separate classes to their enclosing classes, is that static inner classes can access static data members of the enclosing class -- or call static methods, for that matter.

Accessing Static Enclosing Class Members from Static Inner Classes



Static inner classes can access static data members of the enclosing class. They can't access non-static data members; after all, you can create an instance of a static inner class without creating any instance of the enclosing class.

Below, I've modified the CarParts enclosing class to have a static member variable. The static inner class Wheel accesses that member variable.

CarParts.java:

 
public class CarParts {
    
    private static int factoryID = 123;
    
    public static class Wheel {
        public Wheel() {
            System.out.println("Wheel factory ID: " + factoryID);
        }
    }

    public CarParts() {
        System.out.println("Car Parts object created!");
    }
}
 

App.java:

 
public class App {

    public static void main(String[] args) {
        CarParts.Wheel wheel = new CarParts.Wheel();
    }

}
 
Wheel created with factory ID: 123




Difference Between Static and Non-Static Inner Classes



If, on the other hand, we have a non-static inner class, we do need a reference to an object of the enclosing outer class to instantiate it; instances of non-static inner classes are associated with instances of their enclosing classes. So, if our inner Wheel class is made non-static, it will be associated with a particular CarParts object.

In the code below, I've changed Wheel to be non-static. I've also given CarParts an instance variable which is initialized via its constructor. The Wheel class can now access non-static member variables of CarParts.

Note that we have to change the main method to create an instance of the enclosing class before we can create an instance of the non-static inner class.

CarParts.java, with non-static inner class:

 

public class CarParts {
    
    private int id;
    
    private static int factoryID = 123;
    
    public class Wheel {
        public Wheel() {
            System.out.println("Wheel factory ID: " + factoryID);
            System.out.println("CarParts ID: " + id);
        }
    }

    public CarParts(int id) {
        this.id = id;
        System.out.println("Car Parts object created!");
    }
}
 

App.java:

 
public class App {

    public static void main(String[] args) {
        CarParts carParts = new CarParts(777);
        
        CarParts.Wheel wheel = carParts.new Wheel();
        
        // or ...
        // CarParts.Wheel wheel2 = new CarParts(321).new Wheel();
    }

}
 
Car Parts object created!
Wheel created with factory ID: 123
CarParts ID: 777