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
publ开发者_开发技巧ic 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 :
- Javadoc - StackOverflowError
On the same topic :
- toString() in java
- StackOverFlowError in Java postfix calculator
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.
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());
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
}
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())
+ "]";
}
精彩评论