6.4 The static and final Keywords In Depth
static and final are among the most frequently used keywords in Java. Understanding their precise meaning and usage lets you write cleaner, more efficient code.
1. The static Keyword
When static is applied, that member belongs to the class itself, not to any particular instance. You can use it without creating an object.
1.1 Static Variables (Class Variables)
A static variable is shared by all instances. It is loaded into memory exactly once when the JVM loads the class.
public class Counter {
static int count = 0; // Shared by all objects
String name; // Each object has its own copy
Counter(String name) {
this.name = name;
count++; // Increment shared counter each time an object is created
}
}
Counter c1 = new Counter("First");
Counter c2 = new Counter("Second");
Counter c3 = new Counter("Third");
System.out.println(Counter.count); // 3 (access via class name!)
1.2 Static Methods
Methods callable without an instance. Cannot use this or access instance variables.
public class MathHelper {
public static int add(int a, int b) { return a + b; }
public static double circleArea(double radius) {
return Math.PI * radius * radius;
}
}
// No object needed!
int result = MathHelper.add(10, 20); // 30
double area = MathHelper.circleArea(5); // 78.53...
1.3 Static Initialization Blocks
Used for complex initialization of static variables. Runs exactly once when the class is first loaded by the JVM.
public class Config {
static final String DB_URL;
static final int MAX_CONNECTIONS;
static {
System.out.println("Loading config...");
DB_URL = System.getenv("DB_URL") != null
? System.getenv("DB_URL")
: "jdbc:mysql://localhost:3306/mydb";
MAX_CONNECTIONS = 10;
}
}
1.4 Static Imports
Use static members without the class name prefix.
import static java.lang.Math.*;
double result = sqrt(pow(3, 2) + pow(4, 2)); // Instead of Math.sqrt, Math.pow
System.out.println(result); // 5.0
2. The final Keyword
final means "cannot be changed anymore."
2.1 Final Variables (Constants)
Once assigned, the value can never change. By convention, constants use UPPER_CASE_WITH_UNDERSCORES.
public class Constants {
public static final double PI = 3.14159265358979;
public static final int MAX_SIZE = 100;
public static final String APP_NAME = "My Java App";
}
System.out.println(Constants.PI);
// Constants.PI = 3.14; // ❌ Compile error!
2.2 Final Methods
Prevents subclasses from overriding the method.
class Animal {
final void breathe() {
System.out.println("Inhaling oxygen."); // Cannot be overridden
}
void sound() { System.out.println("..."); }
}
class Dog extends Animal {
// @Override void breathe() { } // ❌ Compile error!
@Override void sound() { System.out.println("Woof!"); } // OK
}
2.3 Final Classes
Prevents any subclassing. Java's core classes like String and Integer are final for security and immutability guarantees.
final class ImmutablePoint {
private final int x;
private final int y;
ImmutablePoint(int x, int y) { this.x = x; this.y = y; }
public int getX() { return x; }
public int getY() { return y; }
}
// class SpecialPoint extends ImmutablePoint { } // ❌ Compile error!
Real-world patterns for static and final:
-
Constants class pattern: Group related constants in a single
final class.public final class HttpStatus {
public static final int OK = 200;
public static final int NOT_FOUND = 404;
public static final int SERVER_ERROR = 500;
private HttpStatus() {} // Prevent instantiation
} -
Effectively final and lambdas: Local variables used inside lambdas must be final or effectively final (assigned only once). The compiler enforces this automatically.
-
Performance tip: The JVM can inline
static finalprimitive constants at compile time, making them extremely fast.