- Understand static blocks and when they execute
- Learn static initialization order
- Master static initialization best practices
Static Blocks and Initializers in Java
Static blocks run once when the class loads. They let you set up static variables with complex logic that can't fit in a simple assignment.
Static Blocks
Static blocks are marked with static and execute when the JVM loads the class. Once per class, no matter how many objects you create.
Basic Syntax
public class Example {
static {
// Static block code
System.out.println("Static block executed");
}
}
Multiple Static Blocks
A class can have multiple static blocks, and they are executed in the order they appear in the code:
public class DatabaseConnection {
private static Connection connection;
static {
System.out.println("Initializing database driver...");
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
throw new RuntimeException("Failed to load database driver", e);
}
}
static {
System.out.println("Establishing database connection...");
try {
connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb", "user", "password");
} catch (SQLException e) {
throw new RuntimeException("Failed to connect to database", e);
}
}
}
Static Variable Initialization
Direct Initialization
public class Configuration {
public static final String APP_NAME = "MyApp";
public static final int MAX_CONNECTIONS = 10;
public static String configFile = "config.properties";
}
Initialization in Static Blocks
public class Configuration {
public static Properties config;
static {
config = new Properties();
try (FileInputStream fis = new FileInputStream("config.properties")) {
config.load(fis);
} catch (IOException e) {
System.err.println("Failed to load configuration: " + e.getMessage());
// Use default values
config.setProperty("timeout", "30");
config.setProperty("retries", "3");
}
}
}
Execution Order
Static initialization follows a specific order:
- Static fields are initialized in the order they appear
- Static blocks are executed in the order they appear
- Instance initializers (if any) are executed when objects are created
- Constructors are executed when objects are created
Example of Initialization Order
public class InitializationOrder {
// 1. Static field initialization
static int staticField1 = initializeStaticField1();
// 2. Static block
static {
System.out.println("Static block 1");
staticField2 = 20;
}
// 3. Another static field
static int staticField2 = initializeStaticField2();
// 4. Another static block
static {
System.out.println("Static block 2");
}
// Instance initializer
{
System.out.println("Instance initializer");
}
// Constructor
public InitializationOrder() {
System.out.println("Constructor");
}
static int initializeStaticField1() {
System.out.println("Initializing static field 1");
return 10;
}
static int initializeStaticField2() {
System.out.println("Initializing static field 2");
return 15;
}
}
Output when class is loaded:
Initializing static field 1
Static block 1
Initializing static field 2
Static block 2
Output when object is created:
Instance initializer
Constructor
Static Block Use Cases
1. Complex Static Initialization
public class MathConstants {
public static final double[] PRIMES;
static {
List<Double> primeList = new ArrayList<>();
for (int i = 2; i <= 100; i++) {
if (isPrime(i)) {
primeList.add((double) i);
}
}
PRIMES = primeList.stream().mapToDouble(d -> d).toArray();
}
private static boolean isPrime(int n) {
if (n <= 1) return false;
for (int i = 2; i <= Math.sqrt(n); i++) {
if (n % i == 0) return false;
}
return true;
}
}
2. Loading Native Libraries
public class NativeLibraryLoader {
static {
try {
System.loadLibrary("mynative");
System.out.println("Native library loaded successfully");
} catch (UnsatisfiedLinkError e) {
System.err.println("Failed to load native library: " + e.getMessage());
throw new RuntimeException(e);
}
}
public static void useNativeFunction() {
// Call native methods
}
}
3. Logging Configuration
public class LoggerConfig {
static {
// Configure logging only once
System.setProperty("java.util.logging.config.file", "logging.properties");
try {
LogManager.getLogManager().readConfiguration();
} catch (IOException e) {
System.err.println("Failed to configure logging: " + e.getMessage());
}
}
}
Exception Handling in Static Blocks
Static blocks can throw exceptions, but they must be handled carefully since there's no instance to catch them:
public class StaticExceptionExample {
static {
try {
// Code that might throw exception
Class.forName("com.example.RequiredClass");
} catch (ClassNotFoundException e) {
// Log the error
System.err.println("Required class not found: " + e.getMessage());
// Re-throw as unchecked exception to prevent class loading
throw new ExceptionInInitializerError(e);
}
}
}
Static Block Best Practices
1. Keep Static Blocks Simple
Avoid complex logic in static blocks. Move complex initialization to separate methods:
public class GoodExample {
public static final Map<String, String> CONFIG;
static {
CONFIG = loadConfiguration();
}
private static Map<String, String> loadConfiguration() {
// Complex loading logic here
Map<String, String> config = new HashMap<>();
// ... loading logic
return config;
}
}
2. Handle Exceptions Properly
Don't let exceptions escape static blocks unless they prevent proper class initialization:
public class ExceptionHandling {
static {
try {
initializeResources();
} catch (Exception e) {
// Log and handle gracefully if possible
System.err.println("Resource initialization failed: " + e.getMessage());
// Continue with default values or degraded functionality
}
}
}
3. Avoid Side Effects
Static blocks should not have visible side effects that affect program behavior unpredictably.
4. Document Static Dependencies
If your static block depends on other classes being loaded, document this clearly.
Static blocks run once when the class loads—perfect for complex initialization that doesn't fit in a simple assignment. They execute in order from top to bottom, before any instances are created. Keep them simple, handle exceptions properly, and use them sparingly.
