2014-04-23 1 views
1

아래 코드를 고려하면 예외를 throw하지 않고 실행됩니다.클래스가로드되기 전에 new 연산자를 사용할 수있는 이유는 무엇입니까?

public class Test1 { 
    public static int k = 0; 
    public static Test1 t1 = new Test1("t1"); 
    public static Test1 t2 = new Test1("t2"); 
    public static int i = print("i"); 
    public static int n = 99; 
    public int j = print("j"); 
    { 
     print("constructor block"); 
    } 

    static { 
     print("static block"); 
    } 

    public Test1(String str) { 
     System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 
     ++i; 
     ++n; 
    } 

    public static int print(String str) { 
     System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); 
     ++n; 
     return ++i; 
    } 
    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     Test1 t = new Test1("init"); 
    } 

}

출력 : I 디버거로 단계별

1:j i=0 n=0 
2:constructor block i=1 n=1 
3:t1 i=2 n=2 
4:j i=3 n=3 
5:constructor block i=4 n=4 
6:t2 i=5 n=5 
7:i i=6 n=6 
8:static block i=7 n=99 
9:j i=8 n=100 
10:constructor block i=9 n=101 
11:init i=10 n=102 

. 은 clinit 메소드가 init 메소드를 호출하는 것을 볼 수 있습니다. clinit 메서드는 여전히 클래스 로딩의 일부이므로 Test1 클래스가 준비되기 전에 Test1 개체를 인스턴스화 할 수 있습니까?

+0

클래스 (즉, 정적 변수)는 클래스를 처음 사용할 때만 초기화해야합니까? –

+0

나는 i, n, x, z 등을 더 추가해야한다고 생각한다. 더 많은 다른 장소에 인쇄 방법을 붙여 넣고 임의의 반환 값을 추가한다. – FazoM

+0

@Fazovsky 그건별로 도움이되지 않는 코멘트입니다. – Thomas

답변

0
나는 (당신은뿐만 아니라 그렇게 할 수 있습니다) 사양의 정확한 정의를 보이지만 이제 그런 식으로 넣을 수 있도록해야 할 것

다음

은 당신이 가정을 :

class A { 
    static B b = new B(); 
} 

class B { 
    static A a = new A(); 
} 

하는 경우 클래스는 새 인스턴스를 만들기 전에 완전히 초기화되어야합니다. 즉 모든 정적 초기화 프로그램을 실행해야합니다. 교착 상태가 발생합니다. 정적 블록에 새 인스턴스를 만들 수 없도록 설정하면 언어가 심각하게 제한되므로이 문제를 해결할 수있는 방법이 있어야합니다. 내가 말했듯이

,이를 찾아 볼 거라고하지만 AFAIK 기본 순서는 다음과 같이이다 :

  • 클래스는로드 및 정적 변수는 기본값으로 초기화됩니다
  • 생성자가 최고라고으로
  • -down (즉, 서브 클래스의 슈퍼 클래스) 정적 초기화 블록 (즉, 정적 변수뿐만 아니라, 정적 블록을 초기화하는) 제
    • 가 다음
    • 의 인스턴스 초기화 블록 정의
    • 순서라고 현재의 클래스가 실행되고, 당신이 이미 발견
    • 마지막으로 생성자 순서와 혼란에

물론 거기 방법을 실행하지만 정의되지 않은 당신이 끝날 수 있기 때문에 그것은 일반적으로하지 않는 것이 좋습니다/지저분한 행동. 하나의 경우는 서브 클래스에서 오버라이드되고 서브 클래스의 (아직 초기화되지 않은) 필드에 액세스하는 수퍼 클래스 생성자에서 메소드를 호출하는 것입니다.

+0

답장을 보내 주셔서 감사합니다. 이제 코드가 제대로 돌아갈 수 있습니다. 하지만 그 이유를 알고 싶습니다. 나는 사양을 찾았다. 클래스의로드, 링크 및 초기화 만 지정합니다. 하지만 클래스 인스턴스의 인스턴스화에 대해서는 아무 것도 찾을 수 없었습니다. 위의 순서대로 말했듯이 정적 이니셜 라이저 블록은 인스턴스 이니셜 라이저 블록보다 먼저 호출됩니다. 그러나 출력의 첫 번째 줄이 "XX : 정적 블록 i = XX n = XX"이 아닌 이유는 무엇입니까? – Larry

관련 문제