Item 71. 초기화 지연은 신중하게 하라.

초기화 순환성(initialization circularity) 문제를 해소하기 위해서 초기화를 지연시키는 경우에는 동기화 된 접근자(synchronized accessor)를 사용하라.

// 동기화된 접근자를 사용한 객체 필드 초기화 지연 방법
private FieldType field;

synchronized FieldType getField() {
    if (field == null)
        filed = computeFieldValue();
    return field;
}

성능문제 때문에 정적 필드 초기화를 지연시키고 싶을 때는 초기화 지연 담당 클래스(lazy initialization holder class)숙어를 적용하라. (요청 기반 초기화 담당 클래스(initialize-on-demand holder class)숙어라고도 함)

// 정적 필드에 대한 초기화 지연 담당 클래스 숙어
private static class FieldHolder {
    static final FieldType field = computeFieldValue();
}
static FieldType getField() { return FieldHolder.field; }

성능 문제 때문에 객체 필드 초기화를 지연시키고 싶다면 이중 검사(double check)숙어를 사용하라.

// 이중 검사 패턴을 통해 객체 필드 초기화를 지연시키는 숙어
private volatile FieldType field;

FieldType getField() {
    FieldType result = field;
    if (result == null) {   // 첫 번째 검사 (락 없음)
        synchronized(this) {
            result = field;
            if (result == null) // 두 번째 검사 (락 있음)
                field = result = computeFieldValue();
        }
    }
    return result;
}

결론