Skip to content
elephantoo

The static keyword

Lesson 12 of 43 13 min read

Static fields, methods, constants, static blocks, nested classes and when to use each.


Instance fields belong to each object: every Student has its own name. But some data and behaviour belongs to the class as a whole: the total number of students, a shared constant like MAX_CLASS_SIZE, or a utility method like Math.sqrt that needs no object at all. That is what the static keyword is for.

Static fields: one copy per class#

Visitor.java
public class Visitor {
    static int totalVisitors = 0;   // shared by ALL Visitor objects
    String name;                    // each Visitor has its own

    Visitor(String name) {
        this.name = name;
        totalVisitors++;
    }

    public static void main(String[] args) {
        new Visitor("Asha");
        new Visitor("Ben");
        Visitor c = new Visitor("Chen");
        System.out.println(Visitor.totalVisitors);
        System.out.println(c.name);
    }
}
Output
3
Chen
Output
            Visitor class
          totalVisitors = 3     <- one shared variable
         /        |        \
 [name=Asha] [name=Ben] [name=Chen]   <- one name per object

Access static members through the class name: Visitor.totalVisitors. Java also lets you write c.totalVisitors, but that is misleading (it looks per-object), so IDEs warn about it.

Static methods#

A static method is called on the class, not an object. It is perfect for operations that need only their parameters:

MathUtil.java
public class MathUtil {
    static int square(int n) {
        return n * n;
    }

    static boolean isPrime(int n) {
        if (n < 2) return false;
        for (int i = 2; (long) i * i <= n; i++) {
            if (n % i == 0) return false;
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println(MathUtil.square(12));
        System.out.println(isPrime(97) + " " + isPrime(91));  // same class: name alone works
    }
}
Output
144
true false

You use static methods constantly: Math.max, Integer.parseInt, String.valueOf, Arrays.sort, List.of.

The static rules

  • A static method cannot use this, or access instance fields and methods directly, because there is no current object.
  • It can access other static members, and it can create objects and call their instance methods.
StaticRules.java
public class StaticRules {
    int instanceValue = 10;
    static int staticValue = 20;

    void instanceMethod() {
        System.out.println(instanceValue + staticValue);   // instance code sees both
    }

    static void staticMethod() {
        System.out.println(staticValue);
        // System.out.println(instanceValue);   // error: non-static variable cannot be referenced from a static context
        StaticRules obj = new StaticRules();
        System.out.println(obj.instanceValue);  // fine: through an object
        obj.instanceMethod();
    }

    public static void main(String[] args) {
        staticMethod();
    }
}
Output
20
10
30

This explains a famous beginner error. main is static because the JVM must call it before any objects exist. If you want to call instance methods from main, create an object first.

Constants: static final#

A value that never changes and is shared by everyone should be static final. By convention, its name is UPPER_SNAKE_CASE:

Config.java
public class Config {
    static final int MAX_LOGIN_ATTEMPTS = 3;
    static final double GST_RATE = 0.18;
    static final String APP_NAME = "Elephantoo";

    static double withGst(double price) {
        return price * (1 + GST_RATE);
    }

    public static void main(String[] args) {
        System.out.println(APP_NAME + " allows " + MAX_LOGIN_ATTEMPTS + " attempts");
        System.out.printf("%.2f%n", withGst(1000));
        System.out.println(Math.PI + " " + Integer.MAX_VALUE);   // JDK constants
    }
}
Output
Elephantoo allows 3 attempts
1180.00
3.141592653589793 2147483647

final on a reference means the variable cannot point elsewhere, but the object itself may still be mutable. static final List<String> NAMES = new ArrayList<>(); can still have items added. Use List.of(...) for a truly fixed list.

Static initialiser blocks#

When a static field needs more than one line to set up, use a static { ... } block. It runs once, when the class is first initialised:

Lookup.java
import java.util.HashMap;
import java.util.Map;

public class Lookup {
    static final Map<String, Integer> DAYS_IN_MONTH = new HashMap<>();

    static {
        System.out.println("Loading month table...");
        String[] names = {"JAN", "FEB", "MAR"};
        int[] days = {31, 28, 31};
        for (int i = 0; i < names.length; i++) {
            DAYS_IN_MONTH.put(names[i], days[i]);
        }
    }

    public static void main(String[] args) {
        System.out.println(DAYS_IN_MONTH.get("FEB"));
        System.out.println(DAYS_IN_MONTH.get("MAR"));
    }
}
Output
Loading month table...
28
31

(Map and HashMap are covered in the Maps lesson.)

Static nested classes#

A class declared inside another class with static is a static nested class. It is just a normal class whose name is scoped inside the outer one, used to group helpers that only make sense together:

Order.java
public class Order {
    static class Line {
        final String product;
        final int qty;
        final double price;

        Line(String product, int qty, double price) {
            this.product = product;
            this.qty = qty;
            this.price = price;
        }

        double total() {
            return qty * price;
        }
    }

    public static void main(String[] args) {
        Order.Line a = new Order.Line("Mouse", 2, 499);
        Line b = new Line("Keyboard", 1, 1299);   // short name works inside Order
        System.out.println(a.total() + b.total());
    }
}
Output
2297.0

A non-static nested class (an inner class) is tied to an instance of the outer class and can read its fields. Inner classes are less common; prefer static nested classes unless you need that link. The Email.Builder from the previous lesson was a static nested class.

Utility classes#

A class that only groups static helpers, like Math or Arrays, is a utility class. Make it final and give it a private constructor so nobody creates pointless instances:

Strings2.java
public final class Strings2 {
    private Strings2() { }   // no instances

    static String capitalize(String s) {
        if (s == null || s.isEmpty()) return s;
        return Character.toUpperCase(s.charAt(0)) + s.substring(1).toLowerCase();
    }

    static boolean isNullOrBlank(String s) {
        return s == null || s.isBlank();
    }

    public static void main(String[] args) {
        System.out.println(capitalize("eLEPHANT"));
        System.out.println(isNullOrBlank("   "));
    }
}
Output
Elephant
true

Static factory methods#

A popular alternative to constructors is a static method that returns a new object. Unlike constructors, it has a descriptive name and can return cached instances:

Money.java
public class Money {
    private final long paise;

    private Money(long paise) {
        this.paise = paise;
    }

    static Money ofRupees(double rupees) {
        return new Money(Math.round(rupees * 100));
    }

    static Money zero() {
        return new Money(0);
    }

    Money plus(Money other) {
        return new Money(this.paise + other.paise);
    }

    @Override
    public String toString() {
        return String.format("Rs %d.%02d", paise / 100, paise % 100);
    }

    public static void main(String[] args) {
        Money total = Money.zero().plus(Money.ofRupees(19.99)).plus(Money.ofRupees(5.01));
        System.out.println(total);
    }
}
Output
Rs 25.00

The JDK is full of these: List.of, Integer.valueOf, LocalDate.of, Path.of.

Static imports#

import static lets you use static members without the class prefix:

Java
import static java.lang.Math.sqrt;
import static java.lang.Math.PI;

double area = PI * r * r;
double side = sqrt(area);

Use it sparingly: for well-known names such as JUnit's assertEquals it reads nicely, but overused it hides where things come from.

When should something be static?#

Make it static when...Keep it instance when...
it is a constant (static final)each object needs its own value
it is a pure helper that uses only its parametersit reads or changes object state
it counts or caches across all objectsit represents behaviour of one object
it is a factory that creates instances

Be careful with mutable static fields (non-final shared state). They act like global variables: any code can change them, they make testing harder, and they are a source of bugs in multithreaded programs.

Common mistakes#

  • Calling an instance method from main without an object: "non-static method cannot be referenced from a static context".
  • Making fields static "to fix" that error, which accidentally shares one value across all objects.
  • Accessing static members through an instance (obj.COUNT) instead of the class name.
  • Expecting a static final collection to be unmodifiable.

What's next#

Our classes still expose their fields to anyone. Next, encapsulation and access modifiers show you how to protect an object's data and design a clean public API.

Check your understanding

Quick quiz

0/3 answered
  1. 1.A class has static int count; and you create three objects that each do count++ in the constructor. What is count?

  2. 2.Why can't a static method use this?

  3. 3.When does a static initialiser block static { ... } run?

Finished reading?

Mark this lesson complete to track your progress.