2010-12-17 11 views
3

이 Java 코드로 인해 StackOverflowError이 생성되는 이유는 무엇입니까? 이 어떻게 든 재귀 제네릭 형식 매개 변수와 연결되어 이해합니다. 그러나 나는 전체 메커니즘을 분명히 이해하지 못합니다. 여기왜 여기에 StackOverflowError가 생깁니 까?

public class SomeClass<T extends SomeClass> { 

    SomeClass() { 
     new SomeClassKiller(); 
    } 

    private class SomeClassKiller extends SomeClass<T> { 
    } 

    public static void main(String[] args) { 
     new SomeClass(); 
    } 
} 
+0

오류 스택 추적을 살펴 보았습니까? 그것은 당신에게 무슨 일이 일어나고 있는지에 대한 단서를 제공해야합니다. 그것은 타입 매개 변수와 관련이 없습니다 - 만약 당신이 그것들을 제거한다면, 그것은 여전히'StackOverflowError'를 제공합니다. – Jesper

+3

좋은 질문에 stackoverflow. (: –

+0

@Jesper : SomeClassKiller 무한 횟수로 초기화되고 있습니다.하지만 이유를 이해하지 못합니다. – Roman

답변

13

아래 설명 참조 이전, 순환 생성자 체인 서로 그것에서 하나의 생성자를 호출하는 -를도 정말 중요합니까 클래스가 중첩 된 것입니다. 수업이 주로 환산 한 쌍을보고는 더 명백해야한다 :

public class SuperClass 
{ 
    public SuperClass() 
    { 
     new SubClass(); 
    } 
} 

public class SubClass extends SuperClass 
{ 
    public SubClass() 
    { 
     super(); 
    } 
} 

그래서 서브 클래스의 생성자는 슈퍼 클래스의 생성자를 호출 - 새로운를 생성 한 다음, 슈퍼 클래스의 생성자를 호출 새로운 서브 클래스를 생성 하위 클래스, 등등 ... 쾅!

+0

Hehe .. 전 제네릭 문제 가이 문제를 알지 못했습니다 :) – Roman

+0

'super() ;'거의 * this = new SuperClass();와 같습니다. 이제는 분명해야합니다 ... –

2

는 일반 부분은 중요하지 않습니다

public class SomeClass<T extends SomeClass> { 

    SomeClass() {//A 
     new SomeClassKiller();// calls B 
    } 

    private class SomeClassKiller extends SomeClass<T> {//B 
       //calls A 
    } 

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

이는 클래스 SomeClass 및 SomeClassKiller 사이에 일어나는 재귀 생성자 호출이다.

0
public class SomeClass<T extends SomeClass> { 

    SomeClass() { 
     new SomeClassKiller(); 
    } 

    private class SomeClassKiller extends SomeClass<T> { 
     public SomeClassKiller() 
     { 
     super(); //calls the constructor of SomeClass 
     } 
    } 

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

컴파일러에 의해 생성 된 코드는 유는 재귀 적의 SomeClass 및 SomeClassKiller를 호출하는 객체를 생성 그렇게 할 때,이 같은 것입니다.

0

생성자가 위에서 아래로 호출됩니다. 즉, AB에서 파생되면 A의 생성자는 먼저 부모 생성자 (B)를 호출합니다.

new SomeClassKiller()SomeClass의 생성자를 재귀 적으로 호출하고 다른 SomeClassKiller ...을 생성합니다.

0

main() 방법은 기본적으로 부모 생성자를 호출하여 유래가 발생 SomeClassKiller의 새로운 인스턴스를 생성하는 SomeClass생성자를 호출 SomeClass의 새로운 인스턴스를 만드는 것입니다.

스택 오버 플로우가 발생하지 않도록하십시오. 다음과 같이 코드를 변경하십시오.

public class SomeClass<T extends SomeClass> { 

    SomeClass() { 
     new SomeClassKiller(); 
    } 

    private class SomeClassKiller extends SomeClass<T> { 
     public SomeClassKiller(){ 
      //super(); does this by default, but is now commented out and won't be called. 
     } 

    } 

    public static void main(String[] args) { 
     new SomeClass(); 
    } 
} 
관련 문제