简体   繁体   English

为什么我得到StackOverflowError

[英]Why I'm getting StackOverflowError

public class Category {

    private Category parentCategory;
    private Set<Category> childCategories;
    private String name;

    public Category() {
        childCategories = new HashSet<Category>();
    }

    public Category getParentCategory() {
        return parentCategory;
    }

    public void setParentCategory(Category parentCategory) {
        this.parentCategory = parentCategory;
    }

    public Set<Category> getChildCategories() {
        return childCategories;
    }

    public void setChildCategories(Set<Category> childCategories) {
        this.childCategories = childCategories;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Category [childCategories=" + childCategories + ", name="
                + name + ", parentCategory=" + parentCategory + "]";
    }

}


public static void main(String[] args) {
        Category books = new Category();
        books.setName("Books");
        books.setParentCategory(null);

        Category novels = new Category();
        novels.setName("Novels");
        novels.setParentCategory(books);

        books.getChildCategories().add(novels);
        //novels.setChildCategories(null);

        System.out.println("Books > " + books);
    }

The System.out.println is generating the StackOverflowError . System.out.println正在生成StackOverflowError

When you do your toString() , you call the toString() of the children. 当你执行toString() ,你可以调用子toString() No problem here except that you call the toString() of the parent in here. 这里没问题,除了你在这里调用父类的toString() Which will call the toString() of the children, etc. 这将调用孩子的toString()等。

Nice infinite loop. 好的无限循环。

The best way to get rid of it is to change your toString() method into : 摆脱它的最好方法是将toString()方法更改为:

@Override
public String toString() {
    return "Category [childCategories=" + childCategories + ", name="
            + name + ", parentCategory=" + parentCategory.getName() + "]";
}

This way you don't print the parentCategory but only its name, no infinite loop, no StackOverflowError. 这样您就不会打印parentCategory而只打印它的名称,没有无限循环,没有StackOverflowError。

EDIT: As Bolo said below you will need to check that parentCategory is not null, you might have a NullPointerException if it is. 编辑:正如Bolo所说,你需要检查parentCategory是否为null,如果是,则可能有NullPointerException


Resources : 资源:

On the same topic : 在同一主题上:

Since the error is the System.out.println the problem must be in the toString() . 由于错误是System.out.println因此问题必须在toString()

The problem is that toString() prints both parent and child Category object for the one your printing using their toString() method. 问题是toString()使用他们的toString()方法打印您打印的父对象和子Category对象。 So when you print a Category it calls toString() on the parent which calls toString() on the child which calls toString() on the parent which calls toString() on the child and so on until the stack is exhausted. 所以,当你打印一个类别调用toString()上调用父toString()上调用孩子toString()上调用父toString()直到堆栈用尽的孩子等等。

Your toString() is going into recursive tailspin. 你的toString()进入递归的tailspin。 You need to have two toString() ; 你需要有两个toString() ; one for the parent and one for the children. 一个用于父母,一个用于孩子。 Your toString can look like this : 你的toString看起来像这样:

@Override
public String toString() {
     toStringParent(parent);   // This print only parent
     toStringChildren(children);  // This print only children
}

Because each call to Category#toString() produces a ton of other toString s. 因为每次调用Category#toString()产生大量其他toString Notice that printing childCategories causes each element to be printed out (via toString ), which in turn repeats this entire process of many toString method calls. 请注意,打印childCategories会导致打印出每个元素(通过toString ),这反过来会重复许多toString方法调用的整个过程。

Not only that, but each child calls toString on its parent, which in turn calls toString on its children, which each calling toString on the parent, which in turn calls toString on its children, which... 不仅如此,但每个孩子要求toString其母公司,后者又调用toString它的孩子,每个调用toString父,进而调用toString其子女,这...

return "Category [childCategories=" + childCategories + ", name="
                + name + ", parentCategory=" + parentCategory + "]";

you are using instances like parentCategory to concat to your toString. 您正在使用parentCategory实例parentCategory到toString。 it will call toString method of these instances. 它会调用这些实例的toString方法。

this loop of toString calls never end. 这个toString调用循环永远不会结束。 because child Category will call Parent Category and Parent will call Childs again and so... 因为子类别将调用父类别,而父类将再次调用Childs,所以......

not that if you put: System.out.println(myObject); 如果你把它放在: System.out.println(myObject); it actually is: System.out.println(myObject.toString()); 它实际上是: System.out.println(myObject.toString());

StackOverflowError is actually raised while building the String argument that would be passed to System.out.println . 实际上,在构建将传递给System.out.printlnString参数时引发StackOverflowError

Each time you concatenate a String and a Category , the toString() method of Category is executed. 每次连接一个String和一个CategorytoString()方法Category执行。 The problem is that your toString() in Category is a bit too verbose. 问题是你的Category中的toString()有点过于冗长。 One way to fix it is to print only the name of the parent category (skipping it's parent and children): 修复它的一种方法是只打印父类别的名称(跳过它的父级和子级):

@Override
public String toString() {
    return "Category [childCategories=" + childCategories + ", name="
            + name + ", parentCategory="
            + ((parentCategory == null) ? null : parentCategory.getName())
            + "]";
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM