《Effective Java》解读第12条:始终要覆盖toString
文章目录
- 始终要覆盖toString精华总结
- 为什么要覆盖toString?
- 一个好的toString是什么样的?
- 如何实现一个好的toString?
- 注意
始终要覆盖toString精华总结
提供一个好的toString实现,能让你的类用起来更加舒适,系统的调试和日志记录也更加容易。
为什么要覆盖toString?
- 默认实现无价值:Object类的默认toString实现(类名@散列码,如PhoneNumber@163b91)几乎不提供任何有价值的信息。
- 方便调试:开发者调试测试时,覆盖toString输出一些关键信息可以直观的了解对象状态。例如{Jenny= Phon Number@l63b91 }或 {Jenny = 707-867-5309 },你更愿意看到哪一个。
- 约定:toString 约定指出,“建议所有的子类都覆盖这个方法,返回的字符串应该是一个“简洁但信息丰富,并且易于人们阅读的表达形式”。
一个好的toString是什么样的?
- 包含所有关键信息: 返回值应该包含对象中所有“值得关注”的字段信息。
- 明确返回格式,在文档中进行说明,适合人阅读和机器去解析等。不过,一但指的格式后就要一直坚持,避免破坏依赖此格式的代码或数据。
如何实现一个好的toString?
- 手动拼接
@Override
public String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", city='" + city + '\'' +'}';
}
- 使用format
@Override
public String toString() {return String.format("Person{name='%s', age=%d, city='%s'}", name, age, city);
}
- 工具
用一些可以生成toString的第三方工具或开发工具自动生成。
例如lombok中:

例如idea中:


注意
-
是否包含派生字段: 是否需要包含通过计算得到的字段,取决于它们是否对理解对象状态有帮助。
-
性能考量: 在性能敏感的场景中,如果toString的调用非常频繁,且涉及大量字符串操作,需要考虑其性能影响。
-
安全性: 绝对不要在toString中返回密码、密钥等敏感信息!
-
无需覆盖的情况: 静态工具类、枚举类型(通常已经有很好的名称),或者父类已经提供了合适的toString实现时,可能不需要覆盖。
