itsource

Java의 스태틱/인스턴스 이니셜라이저 블록은 어떤 순서로 실행됩니까?

mycopycode 2022. 9. 6. 22:32
반응형

Java의 스태틱/인스턴스 이니셜라이저 블록은 어떤 순서로 실행됩니까?

프로젝트에 여러 클래스가 포함되어 있고 각 클래스에 정적 이니셜라이저 블록이 있다고 가정합니다.그 블록들은 어떤 순서로 달립니까?클래스 내에서 이러한 블록은 코드에 표시되는 순서대로 실행된다는 것을 알고 있습니다.모든 수업에서 동일하다고 읽었는데, 제가 작성한 샘플 코드가 일치하지 않습니다.이 코드를 사용했습니다.

package pkg;

public class LoadTest {
    public static void main(String[] args) {
        System.out.println("START");
        new Child();
        System.out.println("END");
    }
}

class Parent extends Grandparent {
    // Instance init block
    {
        System.out.println("instance - parent");
    }

    // Constructor
    public Parent() {
        System.out.println("constructor - parent");
    }

    // Static init block
    static {
        System.out.println("static - parent");
    }
}

class Grandparent {
    // Static init block
    static {
        System.out.println("static - grandparent");
    }

    // Instance init block
    {
        System.out.println("instance - grandparent");
    }

    // Constructor
    public Grandparent() {
        System.out.println("constructor - grandparent");
    }
}

class Child extends Parent {
    // Constructor
    public Child() {
        System.out.println("constructor - child");
    }

    // Static init block
    static {
        System.out.println("static - child");
    }

    // Instance init block
    {
        System.out.println("instance - child");
    }
}

다음과 같은 출력을 얻었습니다.

★★★★
static - - 부 staticrent
static - - 모
static - - static
- - " "
- - 할아버지
instance - - instance
- - 부 construct
instance - - instance
- - constructor - constructor - construct construct construct
end

분명한 답은 부모 블록이 자녀 블록보다 먼저 진행된다는 것이지만, 그것은 우연의 일치일 수 있고 두 개의 클래스가 같은 계층에 있지 않다면 도움이 되지 않는다.

편집:

LoadTest.java에 다음 코드를 추가하여 예제 코드를 수정했습니다.

class IAmAClassThatIsNeverUsed {
    // Constructor
    public IAmAClassThatIsNeverUsed() {
        System.out.println("constructor - IAACTINU");
    }

    // Instance init block
    {
        System.out.println("instance - IAACTINU");
    }

    // Static init block
    static {
        System.out.println("static - IAACTINU");
    }
}

클래스 이름에서 알 수 있듯이, 저는 새로운 클래스를 어디서도 참조하지 않았습니다.새 프로그램은 이전 프로그램과 동일한 출력을 냈다.

JLS 버전8의 섹션 12.4와 12.5를 참조해 주세요.이 모든 것에 대해 상세하게 설명합니다(스태틱의 경우 12.4, 변수의 경우 12.5).

정적 초기화의 경우(섹션 12.4):

클래스 또는 인터페이스 타입 T는 다음 중 하나가 처음 발생하기 직전에 초기화됩니다.

  • T는 클래스이며 T의 인스턴스가 생성됩니다.
  • T는 클래스이며 T에 의해 선언된 스태틱 메서드가 호출됩니다.
  • T에 의해 선언된 스태틱필드가 할당됩니다.
  • T에 의해 선언된 정적 필드가 사용되며 이 필드는 상수 변수(θ4.12.4)가 아닙니다.
  • T는 최상위 클래스(θ7.6)이며, T(θ8.1.3) 내에 사전 네스트된 아사트 스테이트먼트(θ14.10)가 실행된다.

(그리고 몇 가지 족제비 같은 조항)

클래스의 스태틱 이니셜라이저는 클래스를 처음 액세스할 때 인스턴스를 만들거나 정적 메서드 또는 필드에 액세스하기 위해 실행됩니다.

따라서 여러 클래스의 경우 이러한 클래스를 로드하기 위해 실행되는 코드에 전적으로 의존합니다.

Keith와 Chris의 답변은 둘 다 훌륭합니다.저는 구체적인 질문에 대해 몇 가지 세부사항을 덧붙입니다.

스태틱 init 블록은 클래스가 초기화되는 순서대로 실행됩니다.그럼, 무슨 순서죠?JLS 12.4.1에 따라:

클래스 또는 인터페이스 타입 T는 다음 중 하나가 처음 발생하기 직전에 초기화됩니다.

  • T는 클래스이며 T의 인스턴스가 생성됩니다.
  • T는 클래스이며 T에 의해 선언된 스태틱 메서드가 호출됩니다.
  • T에 의해 선언된 스태틱필드가 할당됩니다.
  • T에 의해 선언된 정적 필드가 사용되며 이 필드는 상수 변수(θ4.12.4)가 아닙니다.
  • T는 최상위 클래스이며, T 내에 사전 네스트된 아사트 스테이트먼트(θ14.10)가 실행된다.

클래스 클래스 및 패키지 java.lang.reflect에서 특정 반사 메서드를 호출하면 클래스 또는 인터페이스가 초기화됩니다.클래스 또는 인터페이스는 다른 상황에서는 초기화되지 않습니다.

예를 들면, 이 예에서 일어나고 있는 일을 다음에 나타냅니다.

  1. 메인입력
  2. 「START(시작)」를 인쇄합니다.
  3. 하위의 첫 번째 인스턴스를 생성하려고 했습니다. 이 경우 하위의 초기화가 필요합니다.
  4. 하위 초기화를 시도하면 상위 항목이 초기화됩니다.
  5. 상위 항목을 초기화하려고 하면 조부모가 초기화됩니다.
  6. 할아버지 초기화 시작 시 할아버지 정적 초기화 블록이 실행됩니다.
  7. 기술적으로 오브젝트는 조부모의 부모이기 때문에 초기화 체인의 마지막 발언권을 얻지만 아무런 도움이 되지 않습니다.
  8. 조부모의 정적 초기화 블록이 종료된 후 프로그램은 부모의 정적 초기화 블록으로 폴백됩니다.
  9. 부모의 정적 초기화 블록이 종료된 후 프로그램은 자녀의 정적 초기화 블록으로 폴백됩니다.
  10. 이 시점에서 Child가 초기화되므로 해당 생성자는 계속 진행할 수 있습니다.
  11. IAm 이후AClass That Is Never Used는 참조되지 않으며 정적 이니셜라이저 블록을 포함하여 코드가 실행되지 않습니다.
  12. 이 설명서의 나머지 부분은 정적 이니셜라이저에 관한 것이 아니라 완전성을 위해서만 기재되어 있습니다.
  13. 하위 생성자가 암시적으로 super()를 호출합니다(예: 상위 생성자).
  14. 부모 생성자가 암묵적으로 super()를 호출합니다(예: 할아버지 생성자).
  15. 할아버지의 컨스트럭터도 마찬가지입니다만, 효과가 없습니다(또한 오브젝트는 아무것도 할 수 없습니다).
  16. 그랜던트 컨스트럭터가 super()를 호출한 직후에 그랜던트 인스턴스 이니셜라이저 블록이 온다.
  17. 나머지 할아버지 생성자의 생성자가 실행되고 생성자가 종료됩니다.
  18. 프로그램은 super() 호출 직후 부모의 컨스트럭터로 폴백됩니다(즉, 할아버지의 컨스트럭터).
  19. 위와 같이 부모 인스턴스 이니셜라이저가 기능을 수행하며 생성자가 완료됩니다.
  20. 마찬가지로 프로그램은 Child의 Constructor로 돌아와 완료합니다.
  21. 이 시점에서 오브젝트는 인스턴스화 되었습니다.
  22. 「END」를 인쇄
  23. 정상 종료

클래스의 초기화는 정적 이니셜라이저와 클래스에 선언된 정적 필드(클래스 변수)의 이니셜라이저를 실행하는 것으로 구성됩니다.

인터페이스의 초기화는 인터페이스에서 선언된 필드(정수)의 이니셜라이저를 실행하는 것으로 구성됩니다.

클래스를 초기화하기 전에 직접 슈퍼클래스를 초기화해야 하지만 클래스에 의해 구현된 인터페이스는 초기화되지 않습니다.마찬가지로 인터페이스의 슈퍼 인터페이스는 인터페이스가 초기화되기 전에 초기화되지 않습니다.

스태틱 블록이 호출되지 않는 경우가 있습니다.

class Super {
    public static int i=10;
}
class Sub extends Super {
    static {
        system.out.println("Static block called");
    }
}
class Test {
    public static void main (String [] args) {
        system.out.println(Sub.i);
    } 
}

는 " " "를 출력합니다.10


"에디터"에서 업데이트

이에 대한 기술적인 설명은 JLS 12.4.1에 있습니다.

「스태틱 필드(「8.3.1.1」)를 참조하면, 서브 클래스, 서브 인터페이스, 또는 인터페이스를 실장하는 클래스의 이름으로 참조될 수 있어도, 실제로 그것을 선언하는 클래스 또는 인터페이스만이 초기화됩니다.」

하자면, ★★★★★★★★★★★★★★★★★★★★★★.Super.i ★★★★★★★★★★★★★★★★★」Sub.i이며, 이 변수에는 아무것도 .Sub actually actually actually 、 actually 、 actually 、 actually 、 actually actually actually actually actually 。Super.i★★★★★★★★★★★★★★★★★★★★★★★★★★★

(초기화 표현식)이.Super.i「」을 했다.Sub하지만 초기화 순서로 사이클을 갖게 됩니다.JLS 12.4.1JLS 12.4.2를 주의 깊게 읽으면 이것이 가능함을 알 수 있으며 실제로 어떤 일이 일어날지 정확하게 알 수 있습니다.)

따라서 같은 클래스에 여러 개의 스태틱 이니셜라이저와 인스턴스 이니셜라이저를 포함할 수 있습니다.

  • 스태틱 이니셜라이저는 선언된 텍스트 순서로 호출됩니다(12.4.2부터).
  • 인스턴스 이니셜라이저는 선언된 텍스트 순서로 호출됩니다(12.5부터).

각각이 단일 블록인 것처럼 실행됩니다.

class A {
  public A() { 
    // 2
  }
}

class B extends A{
  static char x = 'x'; // 0
  char y = 'y'; // 3
  public B() { 
    // 4
  }

  public static void main(String[] args) {
    new B(); // 1
  }
}

코멘트의 숫자는 평가 순서가 작을수록 빠릅니다.

예시에서 보듯이

  1. 정적 변수
  2. 주된
  3. 슈퍼클래스의 컨스트럭터
  4. 인스턴스 변수
  5. 컨스트럭터

http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html

Java 문서를 확인하십시오.

그런 다음 정적 블록이 아무리 존재하더라도 나타나는 순서대로 단일 블록으로 실행됩니다.

그렇게,

제가 알기로는 자바가 당신의 코드를 보고 있습니다.

static{
i=1;
i=2;
}

정적 inti;

이것이 출력 2를 얻는 이유입니다.

이것이 도움이 되기를 바란다

언급URL : https://stackoverflow.com/questions/2007666/in-what-order-do-static-instance-initializer-blocks-in-java-run

반응형