정적 초기화 블록
정적 멤버는 클래스에 고정된 멤버로, 객체를 생성하지 않고 사용할 수 있다.
정적 필드는 보통 필드 선언과 동시에 초기 값을 주지만, 계산이 필요한 초기화 작업인 경우 static 블록을 생성하여 해당 블록 내에서 초기화해주기도 한다.
정적 블록은 클래스가 메모리로 로딩될 때 자동적으로 실행되며, 여러 개의 정적 블록이 선언되어 있는 경우 선언된 순서대로 실행된다.
정적 메서드와 정적 블록은 객체가 없어도 실행되기 때문에 해당 {} 내에 인스턴스 필드나 인스턴스 메서드를 사용할 수 없다. 그리고 this 키워드도 사용이 불가능하다. 따라서 정적 메서드와 정적 블록에서 인스턴스 멤버를 사용하기 위해서는 객체를 먼저 생성한 뒤 참조 변수로 접근해야 한다.
public class MyClass {
int field1; // 인스턴스 필드
void method1() {} // 인스턴스 메서드
static int field2; // 정적 필드
static void method2() {} // 정적 메서드
// 정적 블록
static {
field1 = 10; // 오류
method1(); // 오류
field2 = 10; // 정상 실행
method2(); // 정상 실행
}
// 정적 메서드
static void method3 {
this.field1 = 10; // 오류
this.method1(); // 오류
field2 = 10; // 정상 실행
method2(); // 정상 실행
}
}
인스턴스 필드 field1과 인스턴스 메서드 method1()을 선언하고, 정적 필드 field2와 정적 메서드 method2()를 선언한다.
정적 블록(static {}) 내에서 인스턴스 필드와 인스턴스 메서드를 그냥 호출하면 컴파일 에러가 발생한다. 정적 블록 내에서 인스턴스 멤버 사용 시 객체를 생성한 뒤 참조 변수로 접근해야 한다.
method3 정적 메서드에서 객체 자신을 참조하는 this 키워드도 사용할 수 없으므로 컴파일 에러가 발생한다.
With 싱글톤
static을 사용하여 만드는 디자인 패턴 중 싱글턴이 있다.
public class SingletonTest {
private int num;
private SingletonTest() {
num = 100;
}
private static SingletonTest instance = null;
public static SingletonTest getInstance() {
if (instance == null)
instance = new SingletonTest();
return instance;
}
}
싱글톤 패턴은 이처럼 정적 필드와 정적 메서드를 사용하여 구현할 수 있다.
외부에서 싱글톤 객체를 얻을 수 있는 방법은 getInstance() 메서드를 호출하는 방법밖에 없다.
getInstance() 메서드에서 반환하는 값은 단 한 개의 객체이므로 싱글톤이 보장된다.
여기서 단 하나의 객체는 instance 변수명으로 선언된 것인데, 이는 static으로 선언된 정적 필드이고 private 접근 제한자를 붙임으로써 한 번만 생성되고 외부에서 값을 변경하지 못하게 한다.