toString() 方法
toString 是什么?
toString() 返回对象的字符串表示,用于日志输出、调试、打印对象内容。
Object 的默认实现返回一个没用的字符串:
java
Person p = new Person("张三", 25);
System.out.println(p); // Person@15db9742 —— 你能看出什么?重写后:
java
Person{name='张三', age=25} —— 一目了然重写 toString
基本模式
java
class Person {
private String name;
private int age;
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}Lombok 注解
java
@Data // @Data 包含 @ToString
class Person {
private String name;
private int age;
}
// 等价于
class Person {
private String name;
private int age;
@Override
public String toString() {
return "Person(name=" + name + ", age=" + age + ")";
}
}排除敏感字段
java
@Data
@ToString(exclude = {"password", "secretKey"})
class User {
private String username;
private String password; // 不打印
private String secretKey; // 不打印
}toString 的使用场景
1. 日志输出
java
class Order {
private String orderId;
private double amount;
@Override
public String toString() {
return "Order{orderId='" + orderId + "', amount=" + amount + "}";
}
}
// 日志中直接打印
Order order = new Order("ORD001", 99.9);
log.info("创建订单: {}", order);
// 输出: 创建订单: Order{orderId='ORD001', amount=99.9}2. 调试输出
java
// IDE 调试时,对象默认调用 toString
System.out.println(person); // 快速查看对象内容
// 集合的 toString 也有用
List<Person> list = Arrays.asList(p1, p2, p3);
System.out.println(list);
// 输出: [Person{name='张三'}, Person{name='李四'}, Person{name='王五'}]3. 字符串拼接
java
// 不用 toString
System.out.println("用户信息: " + user.getName() + ", " + user.getAge());
// 用 toString
System.out.println("用户信息: " + user); // 更简洁常见模式
格式化 toString
java
@Override
public String toString() {
return String.format("Person{name='%s', age=%d, salary=%.2f}",
name, age, salary);
}StringBuilder 拼接
java
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Person{");
sb.append("name='").append(name).append('\'');
sb.append(", age=").append(age);
sb.append('}');
return sb.toString();
}递归引用(小心 StackOverflow)
java
class Node {
private String value;
private Node next;
@Override
public String toString() {
return "Node{value='" + value + "', next=" + next + "}";
// ❌ 如果链表很长,会 StackOverflowError!
}
}
// 安全版本:限制深度
@Override
public String toString() {
return "Node{value='" + value + "'}";
}集合的 toString
Java 集合已经正确重写了 toString:
java
List<String> list = Arrays.asList("a", "b", "c");
System.out.println(list); // [a, b, c]
Map<String, Integer> map = Map.of("a", 1, "b", 2);
System.out.println(map); // {a=1, b=2}
Set<Integer> set = new HashSet<>(Arrays.asList(1, 2, 3));
System.out.println(set); // [1, 2, 3]自定义对象的集合也能正确显示,但前提是集合里的对象正确重写了 toString。
不重写 toString 的后果
java
class Broken {
private String name;
private int value;
}
// 使用
Broken b = new Broken("test", 42);
System.out.println(b);
// 输出: Broken@15db9742 —— 完全不知道内容是什么!调试时看到这种输出,只能靠 IDE 的变量窗口,或者打断点去看属性值。
总结
| 场景 | 建议 |
|---|---|
| 日常调试 | 重写 toString,一眼看穿对象内容 |
| 日志输出 | 重写 toString,避免手动拼接 |
| API 返回 | 谨慎重写,可能暴露内部结构 |
| 集合元素 | 必须重写 toString,集合打印才有用 |
记住:toString 是给自己调试用的,优先保证可读性。
