[java] 정적 클래스 초기화는 언제 발생합니까?

정적 필드는 언제 초기화됩니까? 클래스를 인스턴스화하지 않고 정적 필드에 액세스하는 경우 모든 정적 블록과 개인 정적 필드를 인스턴스화하는 데 사용되는 개인 정적 메서드가 그 순간에 (순서대로) 호출됩니까?

정적 메서드를 호출하면 어떻게됩니까? 또한 모든 정적 블록을 실행합니까? 방법 전에?



답변

클래스의 정적 초기화는 일반적으로 다음 이벤트 중 하나가 처음 발생하기 직전에 발생합니다.

  • 클래스의 인스턴스가 생성되고
  • 클래스의 정적 메서드가 호출됩니다.
  • 클래스의 정적 필드가 할당됩니다.
  • 상수가 아닌 정적 필드가 사용되거나
  • 최상위 클래스의 경우 클래스 내에 어휘 적으로 중첩 된 assert 문이 실행됩니다 1 .

JLS 12.4.1을 참조하십시오 .

Class.forName(fqn, true, classLoader)또는 짧은 형식 을 사용하여 클래스를 강제로 초기화 할 수도 있습니다 (아직 초기화되지 않은 경우).Class.forName(fqn)


1-마지막 글 머리 기호는 Java 6에서 Java 8까지의 JLS에 있었지만 분명히 사양에있는 실수였습니다. Java 9 JLS에서 마침내 수정되었습니다 . 소스 참조 .


답변

정적 필드는 정적 이니셜 라이저 및 정적 필드의 초기화를 포함하는 클래스 로딩 (로드, 링크 및 초기화) 의 초기화 “단계” 중에 초기화 됩니다. 정적 이니셜 라이저는 클래스에 정의 된 텍스트 순서로 실행됩니다.

예를 고려하십시오.

public class Test {

   static String sayHello()  {
      return a;
   }

   static String b = sayHello(); // a static method is called to assign value to b.
                                 // but its a has not been initialized yet.

   static String a = "hello";

   static String c = sayHello(); // assignes "hello" to variable c

    public static void main(String[] arg) throws Throwable {
         System.out.println(Test.b); // prints null
         System.out.println(Test.sayHello()); // prints "hello"
    }
}

정적 범위에서를 호출 null했을 때 sayHello정적 변수 a가 초기화되지 않았기 때문에 Test.b가 인쇄 됩니다 .


답변

예, 모든 정적 이니셜 라이저는 클래스에 처음 액세스하기 전에 실행됩니다. 다른 방법이라면 버그라고 부를 것입니다.


답변