Java Static Variables, Methods, Initializers, and Classes
Static Variables
Static variables are called class variables and are variables defined at the class level. They are marked with the static keyword and can be marked with any access modifier. With instance variables, each class instance will have its own set of variables. With class variables, only one copy of that variable exists that each instance shares.
public class MyClass {
public static int counter = 0;
}
This defines a class variable named counter. You can access counter inside MyClass just like an instance variable or in another class with the following:
final int currentCount = MyClass.counter;
Variables that are marked with both static and final are constants. Constants are written using screaming snake case.
public class Table {
public static final int HEADER_ROW_INDEX = 0;
}
Static Methods
Static methods, just like static variables, only have one copy that each instance shares. They are written just like a regular method but with the static keyword. They can be defined on both classes and interfaces.
public class MyClass {
public static void method() {
}
}
Invoking this method is the same if you are inside the MyClass. If you are outside MyClass, you can invoke this method with the following:
MyClass.method();
Only class variables can be accessed inside of static methods. Static methods can be accessed in static and non-static methods.
public class MyClass {
public void sayHello() {
print("Hello World");
}
public static void sayGoodbye() {
print("Goodbye!");
}
private static void print(final String text) {
System.out.println(text);
}
}
When working with inheritance, you can have class variables and static methods defined in a superclass or a subclass.
public abstract class ParentClass {
public static void parentStaticMethod() {
}
}
public class ChildClass extends ParentClass {
public static void childStaticMethod() {
}
}
When invoking these methods, you can do it with the following:
ParentClass.parentStaticMethod();
ChildClass.parentStaticMethod();
ChildClass.childStaticMethod();
Static Initializers
A static initializer is a block of code that is called once when the class is initialized. They will only ever be called once. A class can have zero or more static initializers. They are useful for initializing class variables when it takes more than one line of code to do so.
public class MyClass {
private static int counter;
static {
counter = 0;
}
}
When a class is initialized, it will first initialize the static variables and then call the static initializers in the order they are defined in the class.
Static Classes
Static classes are called nested classes and are inner classes marked as static. Static in this context is different than a class variable or a static method. Static means that it doesn't have access to variables and methods that are inside the class it is defined in and vice versa. Nested classes are completely independent, as if they were in their own file. It can still access static methods and variables.
public class OuterClass {
public static class NestedClass {
// ...
}
}
You can create instances of a nested class just like normal classes. If you are outside OuterClass, you create instances with the following:
final var nestedClass = new OuterClass.NestedClass();
Conclusion
Static variables are great when you need one copy of a variable. Static methods are a way to write pure functions but can also be more of a procedural way of programming. Nested classes are a way to encapsulate a class and not share variables and methods with the class it is defined in. Using static is great to reduce memory but can introduce global state and can make writing unit tests difficult. Only use static when the use case makes sense.