简体   繁体   中英

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 .

When you do your toString() , you call the toString() of the children. No problem here except that you call the toString() of the parent in here. Which will call the toString() of the children, etc.

Nice infinite loop.

The best way to get rid of it is to change your toString() method into :

@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.

EDIT: As Bolo said below you will need to check that parentCategory is not null, you might have a NullPointerException if it is.


Resources :

On the same topic :

Since the error is the System.out.println the problem must be in the toString() .

The problem is that toString() prints both parent and child Category object for the one your printing using their toString() method. 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.

Your toString() is going into recursive tailspin. You need to have two toString() ; one for the parent and one for the children. Your toString can look like this :

@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. 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.

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...

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

you are using instances like parentCategory to concat to your toString. it will call toString method of these instances.

this loop of toString calls never end. because child Category will call Parent Category and Parent will call Childs again and so...

not that if you put: System.out.println(myObject); it actually is: System.out.println(myObject.toString());

StackOverflowError is actually raised while building the String argument that would be passed to System.out.println .

Each time you concatenate a String and a Category , the toString() method of Category is executed. The problem is that your toString() in Category is a bit too verbose. 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())
            + "]";
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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