정적 필드는 언제 초기화됩니까? 클래스를 인스턴스화하지 않고 정적 필드에 액세스하는 경우 모든 정적 블록과 개인 정적 필드를 인스턴스화하는 데 사용되는 개인 정적 메서드가 그 순간에 (순서대로) 호출됩니까?
정적 메서드를 호출하면 어떻게됩니까? 또한 모든 정적 블록을 실행합니까? 방법 전에?
답변
클래스의 정적 초기화는 일반적으로 다음 이벤트 중 하나가 처음 발생하기 직전에 발생합니다.
- 클래스의 인스턴스가 생성되고
- 클래스의 정적 메서드가 호출됩니다.
- 클래스의 정적 필드가 할당됩니다.
- 상수가 아닌 정적 필드가 사용되거나
최상위 클래스의 경우 클래스 내에 어휘 적으로 중첩 된 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가 인쇄 됩니다 .
답변
예, 모든 정적 이니셜 라이저는 클래스에 처음 액세스하기 전에 실행됩니다. 다른 방법이라면 버그라고 부를 것입니다.