Understanding the Java static Keyword: Variables, Methods, Blocks, and Advanced Uses
This article provides a comprehensive guide to Java's static keyword, covering its use on variables, methods, code blocks, inner classes, static imports, memory placement, lifecycle, serialization, class‑loading order, and common patterns such as logging and the double‑checked‑locking singleton.
The static keyword is a fundamental part of Java, allowing members to belong to the class itself rather than to any instance; it can modify variables, methods, code blocks, inner classes, and imports.
Static variables (also called class variables) are declared with static and stored in the JVM method area. Example:
public class TestStatic {
static int i = 10; // class variable
}Static variables are accessed via ClassName.variableName without creating an object. They share a single copy across all instances.
Static methods are declared with static and cannot use this or call non‑static members directly. Example:
static void sayHello() {
// method body
}Because they belong to the class, static methods can be invoked as ClassName.methodName() . The main method is a classic static method.
Static code blocks are written as static { ... } . They run once when the class is first loaded, allowing initialization logic that must execute before any instance is created.
static {
// initialization code executed once
}Static inner classes are declared with static class . They can contain both static and non‑static members, but unlike non‑static inner classes they do not hold an implicit reference to the outer class instance.
public class ClassDemo {
private int a = 10;
private static int b = 20;
static class StaticClass {
public static int c = 30;
public int d = 40;
public static void print() {
System.out.println("b = " + b);
}
}
}Static imports use import static to bring static members into the current namespace, e.g., import static java.lang.Integer.*; , allowing direct use of MAX_VALUE or toHexString() without class qualification.
import static java.lang.Integer.*;
public class StaticTest {
public static void main(String[] args) {
System.out.println(MAX_VALUE);
System.out.println(toHexString(111));
}
}In terms of memory, static fields reside in the JVM's method area , while instance fields live on the heap. Consequently, static variables share the class lifecycle and are created when the class is loaded and discarded when the class is unloaded.
Static fields are not serialized because serialization only captures heap objects; marking a field as transient also prevents its serialization.
The class‑loading sequence for static members is: parent static fields → parent static blocks → child static fields → child static blocks → parent instance fields → parent instance blocks → parent constructor → child instance fields → child instance blocks → child constructor.
Common practical uses of static include defining a shared logger:
private static final Logger LOGGER = LogFactory.getLogger(StaticTest.class);and implementing the singleton pattern. A classic double‑checked‑locking singleton looks like:
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}The double check prevents multiple threads from creating separate instances. Although constructors are not declared static , they behave like instance methods and cannot be invoked without an object; the JVM uses invokespecial for constructors and invokestatic for static methods.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.