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);
}
System.out.println
генерирует StackOverflowError
.
Когда вы выполняете toString()
, вы вызываете toString()
дочерних элементов. Здесь нет проблем, за исключением того, что здесь вы вызываете toString()
родителя. Который вызовет toString()
дочерних элементов и т.д.
Хороший бесконечный цикл.
Лучший способ избавиться от него — изменить метод toString()
на :
@Override
public String toString() {
return "Category [childCategories=" + childCategories + ", name="
+ name + ", parentCategory=" + parentCategory.getName() + "]";
}
Таким образом, вы не печатаете parentCategory, а только его имя, без бесконечного цикла, без StackOverflowError. .
РЕДАКТИРОВАТЬ: Как сказал Боло ниже, вам нужно будет проверить, что parentCategory не является нулевым, у вас может быть NullPointerException
, если это так.
Ресурсы:
По той же теме:
Поскольку ошибка заключается в System.out.println
, проблема должна быть в toString()
.
Проблема в том, что toString()
печатает как родительский, так и дочерний объект Category
для той, которую вы печатаете, используя их метод toString()
. Поэтому, когда вы печатаете категорию, она вызывает toString()
для родителя, который вызывает toString()
для дочернего элемента, который вызывает toString()
для родителя, который вызывает toString()
для дочернего элемента и так далее, пока стек не будет исчерпан.
StackOverflowError
на самом деле возникает при построении аргумента String
, который будет передан в System.out.println
.
Каждый раз, когда вы объединяете String
и Category
, выполняется метод toString()
для Category
. Проблема в том, что ваш toString()
в Категории
слишком многословен. Один из способов исправить это — напечатать только название родительской категории (пропустив родительскую и дочернюю категории):
@Override
public String toString() {
return "Category [childCategories=" + childCategories + ", name="
+ name + ", parentCategory="
+ ((parentCategory == null) ? null : parentCategory.getName())
+ "]";
}
Ваш toString()
входит в рекурсивный штопор. Вам нужно иметь два toString()
; один для родителей и один для детей. Ваш toString
может выглядеть так:
@Override
public String toString() {
toStringParent(parent); // This print only parent
toStringChildren(children); // This print only children
}
Потому что каждый вызов Category#toString()
порождает массу других toString
. Обратите внимание, что печать childCategories
приводит к выводу каждого элемента (через toString
), что, в свою очередь, повторяет весь этот процесс из множества вызовов метода toString
.
Мало того, каждый дочерний элемент вызывает toString
для своего родителя, который, в свою очередь, вызывает toString
для своих дочерних элементов, каждый из которых вызывает toString
для родительского элемента. , который, в свою очередь, вызывает toString
для своих дочерних элементов, что...
return "Category [childCategories=" + childCategories + ", name="
+ name + ", parentCategory=" + parentCategory + "]";
вы используете такие экземпляры, как parentCategory
для присоединения к вашей toString. он вызовет метод toString этих экземпляров.
этот цикл вызовов toString никогда не заканчивается. потому что дочерняя категория вызовет родительскую категорию, а родительская снова вызовет дочернюю и так далее...
не то, что если вы поместите: System.out.println(myObject);
на самом деле это: System .out.println(myObject.toString());