static 멤버(변수와 메서드)는 클래스가 로드되는 시점에 JVM의 메소드 영역(Method Area)에 저장된다. 이들은 프로그램 실행 종료 시까지 메모리에 유지되며, 모든 객체가 공유한다.
Static 변수: 클래스 로드 시 한 번 초기화되고 모든 객체가 동일한 값을 공유한다.
Static 메서드: 클래스 이름으로 직접 호출할 수 있으며, 객체 상태와 관계없이 동작한다.
클래스가 처음 참조되면, JVM은 다음과 같은 단계로 클래스를 로드하고 초기화한다.
static 멤버:
static 멤버를 공유하며, 객체 생성 여부와 관계없이 접근할 수 있다.객체의 인스턴스 멤버:
static 변수:
static 변수를 클래스의 일부분으로 취급한다.static 변수에 대한 정보를 .class 파일 내에 포함시키며, 클래스 로딩 시 static 변수를 초기화할 준비를 한다.static 메서드:
static 메서드는 클래스 이름을 통해 직접 호출할 수 있는 메서드이다.static 메서드를 클래스 레벨에 고유한 메서드로 처리하며, 객체 인스턴스 없이 호출할 수 있도록 .class 파일에 메서드 정보를 기록한다.static 메서드는 클래스가 로드될 때 메모리 상에 한 번만 로드되고, 객체의 상태와는 무관하게 클래스 수준에서만 동작한다.메모리 절약:
static 클래스는 객체를 생성하지 않고 클래스 레벨에서 접근할 수 있기 때문에, 객체 생성으로 인한 메모리 오버헤드가 없다.static 멤버만 메모리에 할당되므로 메모리 효율적이다.성능 향상:
static 메서드를 직접 호출할 수 있기 때문에 성능 상 이점이 있을 수 있다. 객체를 생성하고 초기화하는 비용이 없으므로, 빠른 접근이 가능하다.전역적인 접근:
static 멤버(변수/메서드)는 클래스 수준에서 공통적으로 사용되므로, 여러 객체나 클래스에서 전역적으로 접근할 수 있다.상태 공유:
static 변수는 클래스의 모든 인스턴스 간에 공유되므로, 상태를 공유하는 데 유용하다.상태 공유로 인한 위험:
static 변수를 참조하기 때문에, 여러 스레드나 객체에서 동시에 접근할 경우 동기화 문제나 데이터 손상이 발생할 수 있다.객체 지향의 원칙을 벗어남:
static은 클래스의 인스턴스를 생성하지 않으므로 객체 지향의 특성인 캡슐화나 상속 등과는 잘 맞지 않을 수 있다.static 메서드는 다형성이나 오버라이딩을 지원하지 않으며, 객체 상태를 다루지 않기 때문에 객체 지향 설계의 일관성이 떨어질 수 있다.테스트 어려움:
static 멤버를 테스트하려면, 객체 생성 없이 바로 정적 메서드 호출을 해야 하므로 단위 테스트가 어려울 수 있다.보통 Static 변수나 메서드는 보통 유틸리티 함수로 많이 사용되는데, OOP에 벗어난 경우가 많아서 안티패턴으로 보는 추세인것 같다.
Utility functions are evil (10년전 칼럼..)
| 특성 | static | static final | final |
|---|---|---|---|
| 변수의 특성 | 클래스 수준에서 공유 | 클래스 수준에서 공유, 값이 변경 불가 | 인스턴스 수준에서 값이 한 번만 초기화되고 변경 불가 |
| 변경 가능성 | 변경 가능 | 값 변경 불가 (상수) | 값 변경 불가 (상수) |
| 사용 목적 | 클래스 레벨에서 공유되는 값 | 상수로 사용, 모든 인스턴스에서 동일한 값 | 상수로 사용, 각 객체마다 다른 값 가능 |
| 일반 사용 예 | 인스턴스 없이 클래스 이름으로 접근 | PI, MAX_VALUE와 같은 상수 | 객체마다 다른 값이 필요한 불변 변수 |