π― Static Keyword in Java: Complete Guide
ποΈ What is Static?
Section titled βποΈ What is Static?βUnderstanding static is critical for Java interviews because it intersects with:
- Class loading and initialization
- Memory management and garbage collection
- Method behavior and polymorphism
- Utility class design and patterns
- Performance optimization
π‘ Interview Focus: Static tests your understanding of class vs instance behavior, memory management, and object-oriented design principles.
π§ Core Concept
Section titled βπ§ Core Conceptβ- Allocated once during class loading, not per object
- Shared across all instances of the class
- Accessible without creating an object
π§ What Can Be Static
Section titled βπ§ What Can Be Staticβ| Type | Purpose | Example |
|---|---|---|
| Static Variables | Shared state across instances | public static int counter = 0; |
| Static Methods | Utility behavior | public static int add(int a, int b) |
| Static Blocks | Configuration at class load time | static { /* initialization */ } |
| Static Nested Classes | Logically grouped helpers | public static class Builder |
| Static Imports | Import static members | import static java.lang.Math.PI; |
π¦ Static Memory Management
Section titled βπ¦ Static Memory Managementβπ§ Memory Lifecycle & Garbage Collection
Section titled βπ§ Memory Lifecycle & Garbage Collectionβ| Concept | Behavior |
|---|---|
| Memory Location | Stored in Method Area (part of Metaspace in modern JVMs) |
| GC Eligibility | Lives as long as the class remains loaded in JVM |
| Risk | Holding large static references may lead to memory leaks |
| Initialization | When class is first loaded by ClassLoader |
| Cleanup | When ClassLoader is garbage collected |
β οΈ Warning: In long-running applications (e.g., servers), a static reference to unused objects = memory leak risk.
π Memory Allocation Process
Section titled βπ Memory Allocation Processβpublic class MemoryExample { // Static variable - allocated once when class loads private static final List<String> staticCache = new ArrayList<>();
// Instance variable - allocated for each object private String instanceData;
static { // Static block - runs once during class loading staticCache.add("Item 1"); staticCache.add("Item 2"); }}π§ Static Variables
Section titled βπ§ Static Variablesβπ Basic Static Variables
Section titled βπ Basic Static Variablesβpublic class Counter { private static int count = 0; // Shared across all instances private int instanceId;
public Counter() { instanceId = ++count; // Increment shared counter }
public static int getTotalCount() { return count; // Access static variable }
public int getInstanceId() { return instanceId; }}
// UsageCounter c1 = new Counter(); // count = 1Counter c2 = new Counter(); // count = 2System.out.println(Counter.getTotalCount()); // 2π Static Constants
Section titled βπ Static Constantsβpublic class MathConstants { public static final double PI = 3.14159; public static final double E = 2.71828; public static final int MAX_ITERATIONS = 1000;
// Private constructor to prevent instantiation private MathConstants() {}}
// Usagedouble area = MathConstants.PI * radius * radius;βοΈ Static Variables with Initialization
Section titled ββοΈ Static Variables with Initializationβpublic class Configuration { private static final Properties config = new Properties();
static { try (InputStream input = Configuration.class .getClassLoader() .getResourceAsStream("config.properties")) { if (input != null) { config.load(input); } } catch (IOException e) { throw new RuntimeException("Failed to load config", e); } }
public static String getProperty(String key) { return config.getProperty(key); }}π Static Methods
Section titled βπ Static Methodsβπ οΈ Utility Methods
Section titled βπ οΈ Utility Methodsβpublic class StringUtils { // Private constructor to prevent instantiation private StringUtils() {}
public static boolean isEmpty(String str) { return str == null || str.trim().isEmpty(); }
public static String reverse(String str) { if (str == null) return null; return new StringBuilder(str).reverse().toString(); }
public static String capitalize(String str) { if (isEmpty(str)) return str; return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase(); }}
// UsageString result = StringUtils.capitalize("hello"); // "Hello"π Factory Methods
Section titled βπ Factory Methodsβpublic class ConnectionFactory { private static final String DEFAULT_URL = "jdbc:mysql://localhost:3306/mydb"; private static final String DEFAULT_USER = "root"; private static final String DEFAULT_PASSWORD = "password";
public static Connection createConnection() { return createConnection(DEFAULT_URL, DEFAULT_USER, DEFAULT_PASSWORD); }
public static Connection createConnection(String url, String user, String password) { try { return DriverManager.getConnection(url, user, password); } catch (SQLException e) { throw new RuntimeException("Failed to create connection", e); } }}
// UsageConnection conn = ConnectionFactory.createConnection();π Static Blocks
Section titled βπ Static Blocksβπ Basic Static Block
Section titled βπ Basic Static Blockβpublic class DatabaseConnection { private static Connection connection;
static { try { // Load driver Class.forName("com.mysql.cj.jdbc.Driver");
// Initialize connection connection = DriverManager.getConnection( "jdbc:mysql://localhost:3306/mydb", "username", "password" );
System.out.println("Database connection established"); } catch (Exception e) { System.err.println("Failed to initialize database: " + e.getMessage()); } }
public static Connection getConnection() { return connection; }}π Multiple Static Blocks
Section titled βπ Multiple Static Blocksβpublic class ComplexInitialization { private static final Map<String, String> config = new HashMap<>(); private static final List<String> cache = new ArrayList<>();
// First static block static { System.out.println("First static block executed"); config.put("app.name", "MyApp"); config.put("app.version", "1.0.0"); }
// Second static block static { System.out.println("Second static block executed"); cache.add("item1"); cache.add("item2"); }
// Third static block static { System.out.println("Third static block executed"); // Final initialization config.put("cache.size", String.valueOf(cache.size())); }}ποΈ Static Nested Classes
Section titled βποΈ Static Nested Classesβπ§ Basic Static Nested Class
Section titled βπ§ Basic Static Nested Classβpublic class OuterClass { private static String outerStaticField = "Outer Static"; private String outerInstanceField = "Outer Instance";
// Static nested class public static class StaticNestedClass { private String nestedField = "Nested Field";
public void display() { System.out.println("Accessing outer static field: " + outerStaticField); // Cannot access outerInstanceField - no outer instance reference }
public static void staticMethod() { System.out.println("Static method in nested class"); } }
// Instance method to demonstrate usage public void createNestedInstance() { StaticNestedClass nested = new StaticNestedClass(); nested.display(); }}
// UsageOuterClass.StaticNestedClass nested = new OuterClass.StaticNestedClass();OuterClass.StaticNestedClass.staticMethod();ποΈ Static Nested Class with Builder Pattern
Section titled βποΈ Static Nested Class with Builder Patternβpublic class Person { private final String name; private final int age; private final String email;
private Person(String name, int age, String email) { this.name = name; this.age = age; this.email = email; }
public static class Builder { private String name; private int age; private String email;
public Builder name(String name) { this.name = name; return this; }
public Builder age(int age) { this.age = age; return this; }
public Builder email(String email) { this.email = email; return this; }
public Person build() { if (name == null || name.trim().isEmpty()) { throw new IllegalArgumentException("Name is required"); } return new Person(name, age, email); } }
public static Builder builder() { return new Builder(); }}
// UsagePerson person = Person.builder() .name("John Doe") .age(30) .email("john@example.com") .build();π Static and Inheritance
Section titled βπ Static and Inheritanceβπ« Static Method Hiding (Not Overriding)
Section titled βπ« Static Method Hiding (Not Overriding)βclass Parent { static void display() { System.out.println("Parent static method"); }
void instanceMethod() { System.out.println("Parent instance method"); }}
class Child extends Parent { static void display() { System.out.println("Child static method"); }
@Override void instanceMethod() { System.out.println("Child instance method"); }}
public class StaticInheritance { public static void main(String[] args) { Parent parent = new Parent(); Child child = new Child(); Parent polymorphic = new Child();
// Static methods - resolved at compile time parent.display(); // "Parent static method" child.display(); // "Child static method" polymorphic.display(); // "Parent static method" (reference type matters)
// Instance methods - resolved at runtime parent.instanceMethod(); // "Parent instance method" child.instanceMethod(); // "Child instance method" polymorphic.instanceMethod(); // "Child instance method" (object type matters) }}π Common Pitfalls
Section titled βπ Common Pitfallsβ1. β Accessing Non-Static from Static Context
Section titled β1. β Accessing Non-Static from Static Contextβpublic class StaticPitfalls { private String instanceField = "Instance Field"; private static String staticField = "Static Field";
public static void staticMethod() { // β Bad: Cannot access instance field from static method // System.out.println(instanceField);
// β
Good: Can access static field System.out.println(staticField); }
public void instanceMethod() { // β
Good: Can access both static and instance fields System.out.println(instanceField); System.out.println(staticField); }}2. β οΈ Static Block Execution Order
Section titled β2. β οΈ Static Block Execution Orderβpublic class ExecutionOrder { static { System.out.println("Static block 1"); }
private static String field = initializeField();
static { System.out.println("Static block 2"); }
private static String initializeField() { System.out.println("Field initialization"); return "Field Value"; }
public static void main(String[] args) { System.out.println("Main method"); }}
// Output:// Static block 1// Field initialization// Static block 2// Main methodπ Best Practices
Section titled βπ Best Practicesβ1. β When to Use Static
Section titled β1. β When to Use Staticβ// β
Good: Utility methodspublic class MathUtils { public static double calculateArea(double radius) { return Math.PI * radius * radius; }}
// β
Good: Constantspublic class Constants { public static final int MAX_RETRY_ATTEMPTS = 3; public static final String DEFAULT_ENCODING = "UTF-8";}
// β
Good: Factory methodspublic class ConnectionFactory { public static Connection createConnection() { // Factory logic return new Connection(); }}2. β When NOT to Use Static
Section titled β2. β When NOT to Use Staticβ// β Bad: Stateful operationspublic class UserService { private static User currentUser; // Bad - shared state
public static void setCurrentUser(User user) { currentUser = user; // Thread safety issues }}
// β
Good: Instance-based approachpublic class UserService { private User currentUser;
public void setCurrentUser(User user) { this.currentUser = user; }}