프로그래밍중급/고급 자바 개발자

자바의 클래스 초기화 순서(class initialization order)란 무엇이며, 그것은 어떻게 작동하고 정적 및 비정적 구성원의 초기화 순서를 잘못 이해할 경우 어떤 결과를 초래할 수 있습니까?

Hintsage AI 어시스턴트로 면접 통과

답변.

자바의 클래스 초기화 순서(class initialization order)는 필드, 블록 및 생성자가 어떤 순서로 초기화되는지를 정의합니다. 간단히 말해서:

  1. 정적 필드와 정적 초기화자는 클래스가 JVM에 의해 로드될 때 클래스 내에서 나타나는 순서대로 실행됩니다(클래스당 한 번).
  2. 비정적 필드와 초기화자는 인스턴스를 생성할 때마다 나타나는 순서대로 실행됩니다. 생성자 호출 전에 실행됩니다.
  3. 생성자는 모든 필드와 블록이 초기화된 후에 실행됩니다.

예시

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() -> 어떤 순서입니까?

출력은:

  1. Parent static
  2. Child static
  3. Parent init
  4. Parent constructor
  5. Child init
  6. Child constructor

먼저 부모의 정적 블록, 그 다음 자식의 정적 블록, 그리고 마지막으로 상속 순서에 따라 비정적 블록과 생성자가 초기화됩니다.

함정 질문.

질문: 클래스 내의 정적 초기화자는 언제 실행됩니까:

class Ex {
    static { System.out.println("static"); }
}

— 첫 번째 인스턴스를 생성할 때인가요, 아니면 어떤 정적 메서드/필드에 최초로 접근할 때인가요?

답변: 정적 초기화자는 클래스에 대한 첫 번째 접근(모든 정적 구성원(메서드/필드) 포함) 시에 실행되며, 인스턴스를 생성할 때만 실행되는 것이 아닙니다.

주제에 대한 세부 사항을 모르고 발생한 실제 오류 사례들.


이야기

은행 애플리케이션에서 정적 연결 풀은 정적 블록에서 초기화되었지만, 첫 번째 인스턴스를 만들기 전에 정적 메서드에 접근했기 때문에 연결이 생성되지 않았습니다. 이는 부하 시 NullPointerException으로 이어졌습니다.


이야기

로깅 서비스는 부모 클래스의 생성자 호출 후 초기화되는 비정적 필드에 의존했습니다. 로그는 null 로거에 기록되었고 중요한 오류 메시지가 손실되었습니다.


이야기

개발자가 초기 값을 가진 새 필드를 초기화 블록 뒤에 두었을 때, 블록이 아직 초기화되지 않은 필드를 사용하려고 했기 때문에 애플리케이션 시작 시 오류가 발생하고 원인을 찾기가 어려웠습니다.