Course topics

By WebNest Studio Engineering Team

Java - Core Tutorial

Static Keyword

The static keyword marks a member — a variable, method, block, or nested class — as belonging to the class itself rather than to any individual object. A static member is created once when the class is loaded by the JVM and is shared by every instance of that class, instead of each object getting its own copy.

Why it matters

static decides whether something belongs to each object or to the class as a whole. Used correctly it gives you shared counters, constants and utility methods. Used carelessly it creates hidden global state that every object can change. It also produces one of the most common compile errors for beginners: "non-static variable cannot be referenced from a static context".

Watch: Java Constructors and the static Keyword

A walkthrough that connects constructors with the static keyword: what each object gets for itself, and what the whole class shares.

Watch on YouTube

Static Variables

A static variable (also called a class variable) is allocated once, in a single shared memory location, regardless of how many objects of the class are created. Changing it through any one object is visible through every other object and through the class name directly, because they all refer to the same memory. Static variables are commonly used for values that logically belong to the whole class, such as a running counter of how many objects have been created.

Static Methods

A static method belongs to the class and can be called without creating an object, using ClassName.methodName(). Because a static method has no associated object (no implicit this), it can only directly access other static members — it cannot directly reference instance variables or call instance methods without first obtaining an object reference. This is why main is declared static: the JVM must be able to call it before any object of the class exists.

Static Blocks and Initialization Order

A static block is a section of code wrapped in static { ... } that runs exactly once, when the class is first loaded into the JVM — before any object of that class is created and before the main method runs, if the static block is in the class containing main. Static blocks are used to perform one-time setup for static data that is too complex for a simple inline initializer. If a class has multiple static variables and static blocks, they execute in the exact top-to-bottom order they appear in the source file.

  • Static members are loaded once per class, not once per object.
  • Static methods cannot use this or super, since there is no object context.
  • Static blocks run once, at class-loading time, before any constructor or instance code.

Static vs Instance: Shared State vs Per-Object State

An instance variable gets a fresh copy inside every object, so two objects can hold different values. A static variable has exactly one copy for the whole class, so every object reads and writes the same value. Choose by asking whose data it is: a customer's name belongs to each customer object, while the total number of customers belongs to the class. Constructors usually work on instance state, but they can also update static state, as the counter example shows.

Call Static Members Through the Class Name

Java lets you write object.staticMethod(), but the object is ignored: the compiler decides which method to call from the variable's declared type, and it even works when the variable is null. Because this hides the fact that the member is shared, the compiler warns about it (javac -Xlint:static), and most style guides forbid it. Always write ClassName.member, as in Math.max(a, b) or Counter.getCount().

Constants with static final

Combining static with final creates a class-level constant: one shared value that can never change, such as Math.PI or Integer.MAX_VALUE. By convention constants are named in UPPER_SNAKE_CASE. A class made only of constants and static helper methods (a utility class, like java.lang.Math) usually also has a private constructor, so nobody creates pointless objects of it.

Static Methods Are Hidden, Not Overridden

A subclass can declare a static method with the same signature as one in its parent, but this hides the parent's method rather than overriding it. Overriding is decided at runtime by the actual object; hiding is decided at compile time by the declared type of the variable. So with Animal pet = new Dog(), pet.sound() runs Dog's instance method, while the static kind() still runs Animal's version.

Static Nested Classes

A class declared static inside another class is a static nested class. Unlike an inner class, it does not hold a reference to an outer object, so you can create it with new Outer.Nested() without any Outer instance. It is commonly used for helper types that only make sense alongside the outer class, such as a Builder or a Node in a linked list.

When to Use static, and When Not To

Static fits things that truly belong to the class rather than to any object:

  • Good uses: constants, stateless helper methods (Math.abs, Integer.parseInt), static factory methods (List.of(...)), and the main entry point.
  • Use with care: mutable static fields are global state shared by the whole program. They make code harder to test and are unsafe when several threads change them at once.
  • Avoid: making methods static just to skip creating an object. If a method needs an object's data, it should be an instance method.

Examples

A static counter, a static method, and a static initializer block

Java
public class Counter {
    static int objectCount;

    static {
        System.out.println("Static block: class Counter is being loaded");
        objectCount = 0;
    }

    Counter() {
        objectCount++;
    }

    static int getCount() {
        return objectCount;
    }

    public static void main(String[] args) {
        new Counter();
        new Counter();
        new Counter();
        System.out.println("Objects created: " + Counter.getCount());
    }
}
Output
Static block: class Counter is being loaded
Objects created: 3

One shared static count vs a separate instance count per object

Java
class Visitor {
    static int totalVisitors; // one copy, shared by the whole class
    int visits;               // one copy per object

    void visit() {
        totalVisitors++;
        visits++;
    }
}

public class SharedVsOwn {
    public static void main(String[] args) {
        Visitor asha = new Visitor();
        Visitor ravi = new Visitor();

        asha.visit();
        asha.visit();
        ravi.visit();

        System.out.println("Asha visits: " + asha.visits);
        System.out.println("Ravi visits: " + ravi.visits);
        System.out.println("Total visitors: " + Visitor.totalVisitors);
    }
}
Output
Asha visits: 2
Ravi visits: 1
Total visitors: 3

A utility class with a static final constant and a private constructor

Java
final class Temperature {
    static final double FREEZING_C = 0.0; // a constant: static and final

    private Temperature() { } // utility class: no objects needed

    static double toFahrenheit(double celsius) {
        return celsius * 9 / 5 + 32;
    }
}

public class TemperatureDemo {
    public static void main(String[] args) {
        System.out.println(Temperature.toFahrenheit(Temperature.FREEZING_C));
        System.out.println(Temperature.toFahrenheit(100));
    }
}
Output
32.0
212.0

Static methods are hidden (compile time), instance methods are overridden (runtime)

Java
class Animal {
    static String kind() { return "Animal"; }
    String sound() { return "..."; }
}

class Dog extends Animal {
    static String kind() { return "Dog"; } // hides Animal.kind(), does not override it
    @Override
    String sound() { return "Woof"; }      // overrides Animal.sound()
}

public class HidingDemo {
    public static void main(String[] args) {
        Animal pet = new Dog();
        System.out.println(pet.sound()); // chosen at runtime by the object: Dog
        System.out.println(pet.kind());  // chosen at compile time by the variable type: Animal
    }
}
Output
Woof
Animal

Common Mistakes

  • Trying to access an instance variable directly inside a static method — this fails to compile because static methods have no implicit object to work with.
  • Assuming each object gets its own copy of a static variable, then being confused when changing it through one object affects every other object.
  • Forgetting that a static block runs only once per class load, not once per object creation.
  • Calling an instance (non-static) method from main without first creating an object.
  • Calling a static method through an object (pet.kind()) and expecting the object's class to decide which version runs; static methods are chosen by the declared type.
  • Using mutable static fields as convenient global variables, which makes code hard to test and unsafe across threads.

Exercise

Give every Ticket a unique, increasing id. The class should keep a shared counter, and each new ticket takes the next number.

Expected output: 1, 2, 3, each on its own line.

Java · starter code
class Ticket {
    // TODO: a static counter shared by all tickets
    // TODO: an instance field for this ticket's id

    Ticket() {
        // TODO: increase the counter and store its value as this ticket's id
    }
}

public class TicketDemo {
    public static void main(String[] args) {
        System.out.println(new Ticket().id);
        System.out.println(new Ticket().id);
        System.out.println(new Ticket().id);
    }
}
Show hints
  • The counter must be static so there is one shared copy; the id must not be, so each ticket keeps its own.
  • id = ++counter; increases the counter and stores the new value in one step.
Show solution
Java · solution
class Ticket {
    static int counter = 0;
    int id;

    Ticket() {
        id = ++counter;
    }
}

public class TicketDemo {
    public static void main(String[] args) {
        System.out.println(new Ticket().id); // 1
        System.out.println(new Ticket().id); // 2
        System.out.println(new Ticket().id); // 3
    }
}

Quick quiz

1. What happens when a static method refers directly to an instance field of its class?

  • A. It does not compile
  • B. It reads the field of the most recent object
  • C. It reads the default value
  • D. It throws NullPointerException
Show answer

A. A static method has no object to work on, so it cannot use instance members without an explicit object reference.

2. When does a static initializer block run?

  • A. Every time an object is created
  • B. Once, when the class is first loaded
  • C. When main finishes
  • D. Only if called explicitly
Show answer

B. A static block runs a single time during class initialisation, before any object is created.

3. Given Counter c = null;, what happens with c.printTotal() if printTotal is a static method?

  • A. It throws NullPointerException
  • B. It does not compile
  • C. It runs normally
  • D. It returns null
Show answer

C. A static method is resolved from the declared type of the variable, not from the object, so no object is needed. It is still clearer to write Counter.printTotal().

Interview questions

Can a static method be overridden?

Show answer

No. A subclass can declare a static method with the same signature, but that hides the parent's method rather than overriding it. Which one runs is decided at compile time from the declared type of the reference, not from the actual object, so there is no runtime polymorphism for static methods.

When should a method or field be static?

Show answer

When it does not depend on the state of any particular object. Typical cases are constants (static final), utility methods that work only on their arguments, such as Math.max, and factory methods. Mutable static fields should be rare, because they are shared by every object and every thread.

Key Points to Remember

  • Static members belong to the class, not to individual objects, and are shared across all instances.
  • Static methods can only directly access other static members and have no implicit "this".
  • Static blocks run once, at class-loading time, before any object is constructed.
  • Access static members through the class name; static final fields are constants named in UPPER_SNAKE_CASE.
  • A static method in a subclass hides the parent's version; it is never overridden.

Practice in the playground

Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.

Run the examples

Change an input, predict the result, then compare it with the output. Explain why the result changes.

WebNest Studio

Written by

WebNest Studio Engineering Team

Practical lessons from developers working with Java, Python, React, databases and production systems.

Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering