public class InfiniteRecursion {
@Override
public String toString() {
return "address: " + this; // 隱式調用 this.toString() → 無限遞歸
}
public static void main(String[] args) {
System.out.println(new InfiniteRecursion()); // StackOverflowError
}
}
System.out.println(obj) 呼叫 String.valueOf(obj) → obj.toString()。"address: " + this 觸發字串連接,編譯器轉為 new StringBuilder().append("address: ").append(this)。StringBuilder.append(Object) 再次呼叫 this.toString() → 回到第 1 步。StackOverflowError。@Override
public String toString() {
return "address: " + super.toString(); // Object.toString() 返回 "ClassName@hashCode"
}
public class User {
private Long id;
private String name;
private String email;
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "', email='" + email + "'}";
}
}
// Lombok
@Data // 含 @ToString
public class Order {
private Long id;
private BigDecimal amount;
private List- items;
}
// 或 Apache Commons Lang
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
IntelliJ IDEA Generate → toString() 預設模板:
public String toString() {
return "ClassName{" +
"field1=" + field1 +
", field2=" + field2 +
'}';
}
@ToString.Exclude 或手動排除。雙向關聯實體(如 Parent ↔ Child)若雙方 toString 互相調用,同樣會爆棧。
// 解決:排除反向引用
@Data
@ToString(exclude = "parent")
public class Child {
private String name;
private Parent parent;
}
@Data
@ToString(exclude = "children")
public class Parent {
private String name;
private List children;
}
return "..." + this;return "..." + this.field.toString();(若 field 又引用 this)super.toString() 獲取默認標識@ToString / @Data 統一風格exclude