자바의 클래스 초기화 순서(class initialization order)는 필드, 블록 및 생성자가 어떤 순서로 초기화되는지를 정의합니다. 간단히 말해서:
class Parent { static { System.out.println("Parent static"); } { System.out.println("Parent init"); } Parent() { System.out.println("Parent constructor"); } } class Child extends Parent { static { System.out.println("Child static"); } { System.out.println("Child init"); } Child() { System.out.println("Child constructor"); } } // new Child() -> 어떤 순서입니까?
출력은:
먼저 부모의 정적 블록, 그 다음 자식의 정적 블록, 그리고 마지막으로 상속 순서에 따라 비정적 블록과 생성자가 초기화됩니다.
질문: 클래스 내의 정적 초기화자는 언제 실행됩니까:
class Ex {
static { System.out.println("static"); }
}
— 첫 번째 인스턴스를 생성할 때인가요, 아니면 어떤 정적 메서드/필드에 최초로 접근할 때인가요?
답변: 정적 초기화자는 클래스에 대한 첫 번째 접근(모든 정적 구성원(메서드/필드) 포함) 시에 실행되며, 인스턴스를 생성할 때만 실행되는 것이 아닙니다.
이야기
은행 애플리케이션에서 정적 연결 풀은 정적 블록에서 초기화되었지만, 첫 번째 인스턴스를 만들기 전에 정적 메서드에 접근했기 때문에 연결이 생성되지 않았습니다. 이는 부하 시 NullPointerException으로 이어졌습니다.
이야기
로깅 서비스는 부모 클래스의 생성자 호출 후 초기화되는 비정적 필드에 의존했습니다. 로그는 null 로거에 기록되었고 중요한 오류 메시지가 손실되었습니다.
이야기
개발자가 초기 값을 가진 새 필드를 초기화 블록 뒤에 두었을 때, 블록이 아직 초기화되지 않은 필드를 사용하려고 했기 때문에 애플리케이션 시작 시 오류가 발생하고 원인을 찾기가 어려웠습니다.