Set<String> set = new HashSet<>();
set.add("A"); set.add("B");
System.out.println(set); // 輸出: [A, B]
開發者疑惑:HashSet 未覆寫 toString(),為何能直接列印內容?
HashSet → AbstractSet → AbstractCollection → Object
HashSet、AbstractSet 均未覆寫 toString()。AbstractCollection 提供預設實作:// java.util.AbstractCollection
public String toString() {
Iterator<E> it = iterator();
if (!it.hasNext()) return "[]";
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
E e = it.next();
sb.append(e == this ? "(this Collection)" : e);
if (!it.hasNext()) return sb.append(']').toString();
sb.append(',').append(' ');
}
}
Collection 子類必須實作 iterator(),AbstractCollection.toString() 透過迭代器遍歷元素。e == this 檢測自我引用,避免無限遞迴(如 list.add(list))。[elem1, elem2, ...],元素間以 , 分隔。AbstractMap.toString() 同樣提供預設實作,格式為 {key1=value1, key2=value2},依賴 entrySet().iterator()。
toString() 可能產生超大字串導致 OOM,除錯時建議用 set.stream().limit(100).collect(Collectors.toList()) 截取前 N 筆。AbstractCollection,免費獲得合理的 toString();若繼承 Object 需自行實作。HashSet 能直接列印,是因為繼承自 AbstractCollection,後者提供了基於 Iterator 的通用 toString() 實作。這是集合框架「模板方法模式」的經典應用。