IT TIP

이 문이 StackOverflowError를 발생시키지 않는 이유는 무엇입니까?

itqueen 2020. 10. 23. 19:51
반응형

이 문이 StackOverflowError를 발생시키지 않는 이유는 무엇입니까?


다른 질문 에서이 이상한 코드를 방금 보았습니다 . StackOverflowError던져 질 거라고 생각했는데 ...

public class Node {
    private Object one;
    private Object two;
    public static Node NIL = new Node(Node.NIL, Node.NIL);

    public Node(Object one, Object two) {
        this.one = one;
        this.two = two;
    }
}

Node.NIL빌드 자체를 참조 하기 때문에 폭발 할 것이라고 생각했습니다 .

왜 그렇지 않은지 알 수 없습니다.


NIL정적 변수입니다. 클래스가 초기화 될 때 한 번 초기화됩니다. 초기화되면 단일 Node인스턴스가 생성됩니다. 그 생성은 Node다른 Node인스턴스 생성을 트리거하지 않으므로 무한 호출 체인이 없습니다. Node.NIL생성자 호출에 전달 하는 것은 생성자가 호출 될 때 아직 초기화되지 않았기 null때문에 전달하는 것과 동일한 효과 Node.NIL가 있습니다. 따라서 public static Node NIL = new Node(Node.NIL, Node.NIL);동일하다 public static Node NIL = new Node(null, null);.

반면에 NIL인스턴스 변수가이고 Node생성자에 인수로 전달되지 않은 경우 컴파일러가이 경우 생성자에 전달하지 못하게했기 때문에 인스턴스가 생성 될 때마다 초기화됩니다. of Node가 생성되어 새로운 Node인스턴스가 생성되고, 생성 된 다른 NIL인스턴스 변수 가 초기화 되어 StackOverflowError.


변수 NIL 우선 값을 부여 null하고 상부 회 아래쪽으로 초기화. 그것은 아닌 함수를 재귀 적으로 정의되어 있지 않습니다. 초기화되기 전에 사용하는 모든 정적 필드에는 기본값이 있으며 코드는 다음과 같습니다.

public static Node {
    public static Node NIL;

    static {
        NIL = new Node(null /*Node.NIL*/, null /*Node.NIL*/);
    }

    public Node(Object one, Object two) {
        // Assign values to fields
    }
}

이것은 글쓰기와 다르지 않습니다

NIL = null; // set implicitly
NIL = new Node(NIL, NIL);

이와 같은 함수 또는 메서드 를 정의 하면 StackoverflowException이 발생합니다.

Node NIL(Node a, Node b) {
    return NIL(NIL(a, b), NIL(a, b));
}

무한 초기화가 발생하지 않는 이유를 이해하는 핵심은 클래스 Node가 초기화 될 때 JVM이 클래스 를 추적 하고 원래 초기화 내에서 클래스에 대한 재귀 참조 중에 재 초기화를 방지 한다는 것 입니다. 이는 언어 사양의이 섹션에 자세히 설명되어 있습니다 .

Java 프로그래밍 언어는 다중 스레드이기 때문에 다른 스레드가 동일한 클래스 또는 인터페이스를 동시에 초기화하려고 할 수 있으므로 클래스 또는 인터페이스 초기화에는 신중한 동기화가 필요합니다. 클래스 또는 인터페이스의 초기화가 해당 클래스 또는 인터페이스의 초기화의 일부로 재귀 적으로 요청 될 수있는 가능성도 있습니다 . 예를 들어, 클래스 A의 변수 이니셜 라이저는 관련되지 않은 클래스 B의 메소드를 호출 할 수 있으며, 이는 차례로 클래스 A의 메소드를 호출 할 수 있습니다. Java Virtual Machine의 구현은 다음을 사용하여 동기화 및 재귀 초기화를 처리합니다. 다음 절차.

따라서 정적 이니셜 라이저가 정적 인스턴스를 만드는 동안 생성자 호출의 일부로 NIL참조 Node.NIL는 정적 이니셜 라이저를 다시 실행하지 않습니다. 대신 NIL, null이 경우에 참조 가 가지고있는 값을 참조 합니다.

참고 URL : https://stackoverflow.com/questions/41932668/why-doesnt-this-statement-throw-a-stackoverflowerror

반응형