static

인스턴스가 아닌 클래스 자체에 속하는 변수·메서드·블록을 선언하는 키워드입니다.

static 변수 (클래스 변수)

class Counter {
    static int count = 0;   // 모든 인스턴스가 공유
    int id;                 // 인스턴스마다 별도

    Counter() {
        count++;
        this.id = count;
    }
}

Counter a = new Counter();  // count = 1, a.id = 1
Counter b = new Counter();  // count = 2, b.id = 2
Counter.count               // 2  ← 클래스명으로 접근

메모리 위치

[ JVM 메모리 ]

메서드 영역 (Method Area)
  └─ Counter.class
       ├─ static int count    ← 클래스 로딩 시 1번만 생성
       └─ 메서드 bytecode

힙 (Heap)
  ├─ Counter 인스턴스 a (id=1)
  └─ Counter 인스턴스 b (id=2)

static 변수는 클래스 로딩 시 메서드 영역에 1번만 생성 → 모든 인스턴스가 공유.

static 메서드

class MathUtils {
    static int add(int a, int b) { return a + b; }
}

MathUtils.add(1, 2);   // 인스턴스 생성 없이 바로 호출

제약사항:

static 블록

클래스가 처음 로딩될 때 한 번만 실행. 복잡한 static 변수 초기화에 사용.

class Config {
    static final Map<String, String> SETTINGS;

    static {
        SETTINGS = new HashMap<>();
        SETTINGS.put("timeout", "30");
        SETTINGS.put("retries", "3");
    }
}

static 중첩 클래스

class Outer {
    static class StaticNested {
        // Outer 인스턴스 없이 사용 가능
        // Outer의 static 멤버만 접근 가능
    }

    class Inner {
        // Outer 인스턴스 필요
        // Outer의 모든 멤버 접근 가능
    }
}

Outer.StaticNested nested = new Outer.StaticNested(); // O
Outer.Inner inner = new Outer().new Inner();           // Outer 인스턴스 필요

싱글톤 패턴에서의 활용

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

핵심 정리

→ JVM | Runtime Data Area

CSLOG에서 보기