static
one copy per class vs one copy per object.
- chapter
- chapter 03.04
- reading time
- 6 min read
a static field has one copy, owned by the class. an instance field has one copy per object. a static method runs without any object, so there's no this inside it.
static = "belongs to the class". that's the whole keyword.
the picture
think of an office. every employee has their own desk (instance fields: one per object). there's one coffee machine in the kitchen (a static field: one per class). anyone can use it, and if someone drinks the last cup, everyone notices.
1class Ticket {2 static int issued = 0;3 final int id;45 Ticket() {6 issued++;7 id = issued;8 }9}
one issued, shared by all 3. each constructor bumps the same box, so ids come out 1, 2, 3...
new Ticket() a few times, then flip to forgot static. with static, every constructor bumps the one counter in the class's box. without it, each object gets its own counter, bumps it once, and every ticket comes out as #1.that "forgot static" bug compiles fine and looks right in review. it's one keyword.
public class Main {
static class Ticket {
int issued = 0; // oops: one per ticket
final int id;
Ticket() {
issued++;
id = issued;
}
}
public static void main(String[] args) {
Ticket a = new Ticket(), b = new Ticket(), c = new Ticket();
System.out.println(a.id + " " + b.id + " " + c.id);
}
}1 1 1
walk through it
the real program, traced on a real JVM. the box tagged static fields belongs to the class, and it appears the moment the class is first used, before any Ticket exists.
- 1public class Main {
- 2 static class Ticket {
- 3 static int issued = 0;
- 4 final int id;
- 5
- 6 Ticket() {
- 7 issued++;
- 8 id = issued;
- 9 }
- 10 }
- 11
- 12 public static void main(String[] args) {
- 13 Ticket a = new Ticket();
- 14 Ticket b = new Ticket();
- 15 Ticket c = new Ticket();
- 16 System.out.println(a.id + " " + b.id + " " + c.id);
- 17 System.out.println(Ticket.issued);
- 18 }
- 19}
·main is about to touch Ticket for the first time.
issued in the class's box tick 1, 2, 3 while each object's id is set once and never moves. note that no stack slot points at the class's box: static fields are reached through the class, not through a reference.where does that box really live? in HotSpot, static fields sit inside the class's java.lang.Class object, on the heap. the class's metadata (its methods, the constant pool) lives in metaspace. more in the JVM's memory map.
static methods have no this
an instance method is called on an object, and that object arrives as this. a static method is called on the class, so there's no object, so there's no this. which means no instance fields and no instance methods, unless you hand it an object explicitly.
public class Main {
int count = 0;
void greet() {
System.out.println("hi");
}
public static void main(String[] args) {
count++;
greet();
}
}error: non-static variable count cannot be referenced from a static context
error: non-static method greet() cannot be referenced from a static contextthe classic first-week error, because main is static. the fix is to make an object (new Main().greet()), or make the thing static if it really doesn't need an object. (java 25's instance main methods dodge this for small programs: void main() isn't static, so the launcher makes the object for you.)
class Parent {
static String who() { return "parent"; }
}
class Child extends Parent {
static String who() { return "child"; }
}
void main() {
Parent p = new Child();
IO.println(p.who());
Parent nobody = null;
IO.println(nobody.who());
}static init order can bite
static fields are initialized once, in source order, the first time the class is used. if a static initializer creates an instance of the same class, that constructor runs halfway through static init, and sees whatever hasn't been initialized yet as zero.
- 1public class Main {
- 2 static class Config {
- 3 static final Config INSTANCE = new Config();
- 4 static int defaultPort = 8080;
- 5
- 6 final int port;
- 7
- 8 Config() {
- 9 port = defaultPort;
- 10 }
- 11 }
- 12
- 13 public static void main(String[] args) {
- 14 System.out.println(Config.INSTANCE.port);
- 15 System.out.println(Config.defaultPort);
- 16 }
- 17}
·first use of Config. before anything else, the class gets initialized.
defaultPort is still 0. the class's box fills in top to bottom, and the object copied the value before it got there.two fixes: move INSTANCE below the fields it depends on, or make defaultPort a static final compile-time constant. constants are special: javac inlines 8080 straight into the constructor's bytecode, so nobody reads the field at runtime and the order stops mattering. same program with static final int defaultPort = 8080; prints 8080 twice.
what static is actually for
| use | example |
|---|---|
| constants | static final int MAX_RETRIES = 3; |
| utility methods that need no state | Math.max(a, b), List.of(...) |
| factory methods | Integer.valueOf(42), Path.of("a.txt") |
| a nested class that doesn't need an outer object | static class Node (see nested classes) |
main (classic form) | the launcher calls it before any object exists |
| per-class bookkeeping | counters, caches. carefully, and thread-safely |
- static field: one copy, owned by the class. instance field: one per object.
- static methods have no
this, so they can't touch instance members directly. - statics initialize once, in source order, on first use of the class.
- static methods hide, they don't override. the declared type picks.
static finalconstants: great. mutable static state: global variables with extra steps.