views:

183

answers:

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

+7  A: 

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 :

Colin Hebert
You'll get `NullPointerException` instead when `parentCategory == null`.
Bolo
Just `parentCategory.getName()` will not be complete.
fastcodejava
+1  A: 

Because each call to Category#toString() produces a ton of other toStrings. 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...

Shakedown
+1  A: 
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());

mohammad shamsi
+2  A: 

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.

Dave Webb
+2  A: 

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
}
fastcodejava
+1  A: 

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())
            + "]";
    }
Bolo