调用方法时发生java.lang.StackOverflowError错误

3

我正在学习接口的行为。我已经创建了一个接口及其实现类,但在调用方法m1()时,我遇到了java.lang.StackOverflowError错误。我不知道为什么。有没有人能告诉我背后的正确原因!!!以下是代码:

public interface Employee {
     String name="Kavi Temre";
}

public class Kavi implements Employee{
    Employee e= new Kavi();
    public static void main(String[] args) {

        Kavi kt=new Kavi();
        kt.m1();
    }

    void m1()
    {
        System.out.println(Employee.name);
        //System.out.println(e.name);
    }
}

两个sysout都给出了同样的错误:请告诉我这里实际上发生了什么?

控制台输出:

Exception in thread "main" java.lang.StackOverflowError
    at Kavi.<init>(Kavi.java:2)
    at Kavi.<init>(Kavi.java:2)
    at Kavi.<init>(Kavi.java:2)
    at Kavi.<init>(Kavi.java:2)
    at Kavi.<init>(Kavi.java:2)
    at Kavi.<init>(Kavi.java:2)
    at Kavi.<init>(Kavi.java:2)
    .....
2个回答

6

当您调用

Kavi kt=new Kavi();

它初始化e成员:

Employee e = new Kavi();

这段代码会初始化它自己的e成员,从而导致对Kavi构造函数的无限调用。因此会出现堆栈溢出错误。

这等同于:

Employee e;
public Kavi ()
{
    e = new Kavi();
}

构造函数不应该在无限循环中调用自身。

删除Employee e = new Kavi()这一行将解决您的问题。如果您的类必须持有对Employee的引用,请考虑将其传递给构造函数:

public Kavi ()
{
    this.e = null;
}

public Kavi (Employee e)
{
    this.e = e;
}

public static void main(String[] args) {

    Employee e = new Kavi ();
    Kavi kt=new Kavi(e);
    ...
}

一种替代方案是更改:
Employee e = new Kavi();

为了

static Employee e = new Kavi();

如果所有 Kavi 的实例都共享由 e 引用的同一个 Employee 实例,那么这将是一个有效的解决方案。

谢谢 eran。你是对的,但是如果像这样在静态块中放置 Employee e = new Kavi(); static { Employee e= new Kavi(); },那么我就不会得到任何错误。请告诉我为什么会发生这种情况? - kavi temre
@kavitemre 当你在静态初始化块中声明 e 变量时,该块仅在类初始化时执行一次。因此,它不会在每次调用类的构造函数时执行。顺便说一句,这样的声明是无用的,因为该变量将成为静态初始化块的局部变量,所以你将无法从该块外部访问它。 - Eran
我知道。我只是在探索接口和对象初始化。谢谢你的解释。 - kavi temre

2

在你的类Kavi中,你声明了一个类型为Employee的字段e,并用一个新的Kavi对象进行初始化。

当创建类Kavi的第一个实例时,你触发了上述初始化并创建了一个新的Kavi对象(第2行),该对象还创建了一个新的Kavi对象,以此类推。因此,有问题的那一行是

Employee e= new Kavi();

在创建了许多Kavi对象之后,堆栈将达到其限制并抛出异常。


感谢Stefan的解释。我有一个疑问,如果像这样在静态块中放置Employee e= new Kavi(); static { Employee e= new Kavi(); },那么我没有得到任何错误。请告诉我为什么会发生这种情况? - kavi temre
如果Employee e位于静态块中,则它不是一个对象变量,而是一个类变量。它只会被初始化一次。 - Stefan Freitag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接