program tip

생성자 코드가 Java에서 실행되기 전에 필드가 초기화됩니까?

radiobox 2020. 11. 20. 08:50
반응형

생성자 코드가 Java에서 실행되기 전에 필드가 초기화됩니까?


누구든지 다음 프로그램의 출력을 설명 할 수 있습니까? 생성자가 인스턴스 변수보다 먼저 초기화되었다고 생각했습니다. 그래서 출력이 "XZYY"가 될 것으로 예상했습니다.

class X {
    Y b = new Y();

    X() {
        System.out.print("X");
    }
}

class Y {
    Y() {
        System.out.print("Y");
    }
}

public class Z extends X {
    Y y = new Y();

    Z() {
        System.out.print("Z");
    }

    public static void main(String[] args) {
        new Z();
    }
}

올바른 초기화 순서는 다음과 같습니다.

  1. 클래스가 이전에 초기화되지 않은 경우 텍스트 순서의 정적 변수 이니셜 라이저 및 정적 초기화 블록입니다.
  2. 명시 적이든 암시 적이든 생성자의 super () 호출.
  3. 인스턴스 변수 이니셜 라이저 및 인스턴스 초기화 블록 (텍스트 순서).
  4. super () 이후 생성자의 나머지 본문입니다.

Java Virtual Machine 사양의 섹션 §2.17.5-6을 참조하십시오 .


디 컴파일 된 버전의 클래스 파일을 보면

class X {
    Y b;

    X() {
        b = new Y();
        System.out.print("X");
    }
}

class Y {
    Y() {
        System.out.print("Y");
    }
}

public class Z extends X {

    Y y;

    Z() {
        y = new Y();
        System.out.print("Z");
    }

    public static void main(String args[]) {
        new Z();
    }
}

인스턴스 변수 y가 생성자 내부로 이동 한 것을 알 수 있으므로 실행 순서는 다음과 같습니다.

  1. 생성자 호출 Z
  2. 기본 생성자를 트리거합니다. X
  3. X생성자의 첫 번째 줄 new Y()이 호출됩니다.
  4. Y 인쇄
  5. X 인쇄
  6. 생성자 Z의 첫 번째 줄을 호출합니다. new Y()
  7. 인쇄 Y
  8. Z 인쇄

모든 인스턴스 변수는 생성자 문을 사용하여 초기화됩니다.


정적에 대한 오해를 명확히하기 위해이 작은 코드를 간단히 참조하겠습니다.

public class Foo {
  { System.out.println("Instance Block 1"); }
  static { System.out.println("Static Block 1"); }
  public static final Foo FOO = new Foo();
  { System.out.println("Instance Block 2"); }
  static { System.out.println("Static Block 2 (Weird!!)"); }
  public Foo() { System.out.println("Constructor"); }
  static public void main(String p[]) {
    System.out.println("In Main");
    new Foo();
  }
}

놀랍게도 출력은 다음과 같습니다.

Static Block 1
Instance Block 1
Instance Block 2
Constructor
Static Block 2 (Weird!!)
In Main
Instance Block 1
Instance Block 2
Constructor

참고 우리는 가지고 static {}이라고 그 두 인스턴스를 {}. 이것은 생성자가 처음 호출 될 때 실행 순서를 삽입하여 중간에 생성자를 던지기 때문에 발생합니다.

Discovered this when I was working on this answer - https://stackoverflow.com/a/30837385/744133.

Basically we observe this to happen:

  1. During the first time an object is initialized, Initialize current object for both static and instance initialization intermixed based on order of occurrence

  2. For all next initializations, only do the instance initialization in the order of occurrence, as static initialization already happened.

I need to research how the mix of inheritance, and both explicit and implicit calls to super and this will affect this, and will update with findings. It would be likely similar to the other supplied answers, except that they got it wrong with the static initialization.


When you invoke a constructor, the instance variable initializers run before the body of the constructor. What do you think the output of the below program ?

public class Tester {
    private Tester internalInstance = new Tester();
    public Tester() throws Exception {
        throw new Exception("Boom");
    }
    public static void main(String[] args) {
        try {
            Tester b = new Tester();
            System.out.println("Eye-Opener!");
        } catch (Exception ex) {
            System.out.println("Exception catched");
        }
    }
}

The main method invokes the Tester constructor, which throws an exception. You might expect the catch clause to catch this exception and print Exception catched. But if you tried running it, you found that it does nothing of that sort and It throws a StackOverflowError.


The initialization sequence is specified in JLS 12.5:

1.First, memory is allocated for the new object

2.Then all instance variables in the object (including the ones defined in this class and all of its superclasses) are initialized to their default values

3.Finally, the constructor is called.

https://stackoverflow.com/questions/26552799/which-run-first-default-values-for-instance-variables-or-super-constructors

참고URL : https://stackoverflow.com/questions/14805547/are-fields-initialized-before-constructor-code-is-run-in-java

반응형