2010-12-17 112 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 2010-12-17 11:03:32

+3

在stackoverflow上的好问题。 (: – 2010-12-17 11:03:44

+0

@Jesper:SomeClassKiller正在初始化无限次数,但我不明白为什么。 – Roman 2010-12-17 11:04:41

回答

13

通用部分无关紧要的评论 - 也不是真正的问题该类是嵌套的。看着这主要是相当于对类,它应该是比较明显的:

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

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

所以子类构造函数调用父类的构造 - 然后创建一个新的子类,它调用到超类构造函数,它创建了一个新的子类等...砰!

+0

呵呵..我绝对确信泛型的问题并没有注意到这个东西:) – Roman 2010-12-17 11:07:23

+0

'super() ;'*几乎等于'this = new SuperClass();'。现在应该很明显... – 2010-12-17 11:07:53

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(); 
    } 
} 

由编译器产生的代码是这样的,所以当u创建一个对象,它recursivly调用SomeClass的和SomeClassKiller永远。

0

构造函数是从上到下调用​​的,也就是说,如果A类从B派生,A的构造函数将首先调用父构造函数(B)。

在你的情况下,new SomeClassKiller()递归地调用SomeClass的构造函数,这又构造了另一个SomeClassKiller ......它就是这样。

0

main()方法是创建的SomeClass一个新实例,它调用SomeClass构造创建,默认情况下调用父类的构造并发生计算器的SomeClassKiller一个新的实例。

为了避免堆栈溢出。将代码更改为如下所示:

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(); 
    } 
} 
相关问题