Home/Learn/Java A–Z/static Keyword

static Keyword

Beginner
OOP & Advanced Classes

Master static fields, methods, initialiser blocks, and nested classes — and understand what belongs to the class versus to each instance.

Overview

The static keyword declares members that belong to the class itself rather than to any particular instance. There is one copy of a static field shared by all instances. Static methods can be called without creating an object. Static initialiser blocks run once when the class is first loaded by the ClassLoader. Understanding static is essential for utility classes (Math, Arrays, Collections), constants, factory methods, and the Singleton pattern.

Static Fields & Methods

A static field has one shared value for the entire class — all instances read and write the same variable. Changing it from one instance changes it for all. Useful for counters, constants (public static final), and shared caches.

Static methods cannot access instance fields or use this — they have no implicit object. They can only access static members directly. Call them on the class name, not on an instance (though Java allows the latter, it is misleading and discouraged).

Counter.java
public class Counter {
    // Static field — one per class, shared by all instances
    private static int count = 0;

    // Instance field — one per object
    private final int id;
    private String name;

    public Counter(String name) {
        this.name = name;
        this.id   = ++count;  // increment shared counter
    }

    // Static method — belongs to class, no 'this'
    public static int getCount() { return count; }

    // Static constant — public static final by convention in UPPER_SNAKE_CASE
    public static final int MAX_INSTANCES = 100;

    // Static utility method (no state needed)
    public static boolean isValidName(String name) {
        return name != null && !name.isBlank() && name.length() <= 50;
    }

    @Override public String toString() { return "Counter#" + id + "(" + name + ")"; }

    public static void main(String[] args) {
        Counter a = new Counter("alpha");
        Counter b = new Counter("beta");
        Counter c = new Counter("gamma");

        System.out.println(a);                // Counter#1(alpha)
        System.out.println(Counter.getCount()); // 3 — class-level call
        System.out.println(c.getCount());       // also 3 — works but misleading

        System.out.println(Counter.isValidName("hello")); // true
        System.out.println(Counter.MAX_INSTANCES);        // 100
    }
}

Static Initialiser Blocks

A static initialiser block (static { ... }) runs exactly once when the class is first loaded — before any constructor or static method is called. Use it to initialise complex static fields that require more than a simple assignment (e.g., loading a config file, populating a lookup map).

Multiple static blocks in one class run in declaration order. Instance initialiser blocks (without static) run every time an object is constructed, before the constructor body.

CountryCodes.java
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

public class CountryCodes {
    // Static field initialised by static block
    private static final Map<String, String> CODES;

    static {
        // Static initialiser — runs once when class is loaded
        System.out.println("Loading country codes...");
        Map<String, String> map = new HashMap<>();
        map.put("US", "United States");
        map.put("IN", "India");
        map.put("GB", "United Kingdom");
        map.put("DE", "Germany");
        CODES = Collections.unmodifiableMap(map);
        System.out.println("Loaded " + CODES.size() + " codes");
    }

    // Second static block — runs after the first
    static {
        System.out.println("Class fully initialised");
    }

    public static String getCountry(String code) {
        return CODES.getOrDefault(code.toUpperCase(), "Unknown");
    }

    public static void main(String[] args) {
        // First access triggers class loading and both static blocks
        System.out.println(CountryCodes.getCountry("IN")); // India
        System.out.println(CountryCodes.getCountry("JP")); // Unknown

        // Class is NOT reloaded — static blocks don't run again
        System.out.println(CountryCodes.getCountry("US")); // United States
    }
}

Static Nested Classes & Inner Class Contrast

A static nested class is declared inside another class with static. It has no reference to the enclosing instance — it is just a top-level class that happens to be scoped inside another class for logical grouping. It can be instantiated without an enclosing instance.

A non-static inner class holds an implicit reference to the enclosing instance. Each inner class instance is tied to one enclosing instance. This is useful for iterators and builder patterns, but can cause memory leaks if the inner class outlives the outer.

Builder pattern commonly uses static nested classes.

LinkedList.java / Builder pattern
public class LinkedList<T> {
    private Node<T> head;

    // Static nested class — no reference to LinkedList instance needed
    static class Node<T> {
        T data;
        Node<T> next;
        Node(T data) { this.data = data; }
    }

    public void addFirst(T data) {
        Node<T> node = new Node<>(data);  // instantiate without outer instance
        node.next = head;
        head = node;
    }

    // ── Builder pattern with static nested class ──────────────────────────
    public static class Person {
        private final String name;
        private final int age;
        private final String email;

        private Person(Builder b) {
            this.name  = b.name;
            this.age   = b.age;
            this.email = b.email;
        }

        // Static nested Builder
        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()              { return new Person(this); }
        }

        @Override public String toString() {
            return "Person{name=" + name + ", age=" + age + ", email=" + email + "}";
        }

        public static void main(String[] args) {
            Person p = new Person.Builder()
                .name("Alice").age(30).email("alice@example.com")
                .build();
            System.out.println(p);
            // Person{name=Alice, age=30, email=alice@example.com}
        }
    }
}

Key Points to Remember

  • Static fields are class-level — one shared copy for all instances; changes affect all
  • Static methods cannot access instance fields or use this — only static members
  • Static initialisers run once when the class is first loaded, in declaration order
  • Static nested classes have no enclosing-instance reference; non-static inner classes do
  • Non-static inner classes holding outer references can cause memory leaks if they outlive the outer object
  • Call static members on the class name (Counter.getCount()), not on an instance variable

Practice static Keyword in the Playground

Run and modify code directly in your browser - no setup needed.

Interview Questions

Sign in to ask Aria
1

What is the difference between a static field and an instance field?

EasyTCS
2

Can a static method access a non-static instance variable? Why?

EasyInfosys
3

When does a static initialiser block run?

MediumOracle
4

What is the difference between a static nested class and an inner class?

MediumAmazon
5

Why can non-static inner classes cause memory leaks?

MediumGoogle

Ask Aria about static Keyword

Your personal AI tutor — ask anything about this concept