2010-08-29 9 views
9
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.Почему я получаю StackOverflowError

ответ

14

Когда вы делаете свой toString(), вы вызываете toString() детей. Здесь нет проблем, кроме того, что вы вызываете здесь toString() родителя. Который назовет toString() детей и т. Д.

Nice бесконечный цикл.

Лучший способ избавиться от него, чтобы изменить метод toString() в:

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

Таким образом, вы не напечатать parentCategory, но только его имя, ни бесконечный цикл, не StackOverflowError.

EDIT: Как указано ниже, вам нужно будет проверить, что parentCategory не является нулевым, вы можете иметь NullPointerException, если это так.


Ресурсы:

На эту же тему:

+0

Вы получите 'NullPointerException' вместо этого, когда' parentCategory == null'. – Bolo

+0

Просто 'parentCategory.getName()' не будет завершен. – fastcodejava

1

Поскольку каждый вызов Category#toString() производит массу других toString с. Обратите внимание, что печать childCategories заставляет каждый элемент распечатываться (через toString), что, в свою очередь, повторяет весь этот процесс из многих вызовов метода toString.

Не только это, но каждый ребенок называет toString на своих родителей, которые, в свою очередь, вызывает toString на своих детей, каждый из которых призывающих toString на родителя, который, в свою очередь, вызывает toString на своих детей, которые ...

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

Вы используете экземпляры, такие как parentCategory, чтобы выполнить команду toString. он вызовет метод toString этих экземпляров.

Этот цикл вызовов toString никогда не заканчивается. потому что ребенок Категория позвонит Родительская категория и Родитель будет вызывать Чайлдс снова и так ...

не то, что если вы поставите: System.out.println(myObject); это на самом деле: System.out.println(myObject.toString());

2

Поскольку ошибка является System.out.println проблема должна быть в toString().

Проблема заключается в том, что toString() печатает как родительский, так и дочерний объект Category объект для печати, используя их метод toString().Поэтому, когда вы печатаете категорию, он вызывает toString() на родительском объекте, который вызывает у ребенка toString(), который вызывает у родителя toString(), который вызывает у ребенка дочерний элемент toString() и т. Д. До тех пор, пока стек не будет исчерпан.

2

Ваш toString() идет в рекурсивный штопор. Вам нужно иметь два toString(); один для родителя и один для детей. Ваш toString может выглядеть следующим образом:

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

StackOverflowError фактически поднят при строительстве String аргумента, который будет передан System.out.println.

Каждый раз, когда вы сцепить в String и Category, тем toString() метод Category выполняется. Проблема в том, что ваш toString() в Category является слишком подробным. Один из способов исправить это напечатать только название родительской категории (пропуск его родители и дети):

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