首先让我们一起看看Javadoc回忆下Object.toString应当做什么:“返回该对象的字符串表示,该结果必须简明但表述详实易懂。建议所有子类重写该方法”。这里最有趣的就是“简明”和“详实”。通常IDE为我们生成equals/hashcode/toString这些方法。此外,这些IDE提供了许多方式来生成我们自己的toString:字符串连接(使用+号)、StringBuffer、StringBuilder、ToStringBuilder(Commons Lang 3)、 ReflectionToStringBuilder (Commons Lang 3)、Guava或者Objects.toString……该选哪一个?

    用 + 连接字符串
    让我们先从最高效的方法开始:用 + 连接字符串。如今JVM编译器(大部分时候)会把 + 编译成一个string builder。唯一的缺点是null值不会被处理,需要自己来处理它。

    1. public String toString() {
    2. return "MyObject{" +
    3. "att1='" + att1 + ''' +
    4. ", att2='" + att2 + ''' +
    5. ", att3='" + att3 + ''' +
    6. "} " + super.toString();
    7. }
    8. // 使用JMH测出来的平均性能
    9. // (最小, 平均, 最大) = (140772,314, 142075,167, 143844,717)

    用Objects.toString连接字符串
    Java SE 7带来了Objects类和它的一些静态方法。Objects.toString的优点是它可以处理null值,甚至可以给null设置默认值。其性能与上一个相比略低,但是null值可以被处理:

    1. public String toString() {
    2. return "MyObject{" +
    3. "att1='" + Objects.toString(att1) + ''' +
    4. ", att2='" + Objects.toString(att2) + ''' +
    5. ", att3='" + Objects.toString(att3) + ''' +
    6. "} " + super.toString();
    7. }
    8. // 使用JMH测出来的平均性能
    9. // (最小, 平均, 最大) = (138790,233, 140791,365, 142031,847)

    StringBuilder
    另一种技术是使用StringBuilder。

    1. public String toString() {
    2. final StringBuilder sb = new StringBuilder("MyObject{");
    3. sb.append("att1='").append(att1).append(''');
    4. sb.append(", att2='").append(att2).append(''');
    5. sb.append(", att3='").append(att3).append(''');
    6. sb.append(super.toString());
    7. return sb.toString();
    8. }
    9. // 使用JMH测出来的平均性能
    10. // (最小, 平均, 最大) = (96073,645, 141463,438, 146205,910)

    Guava
    Guava有一些helper类:其中一个可以帮助你生成toString。

    1. public String toString() {
    2. return Objects.toStringHelper(this)
    3. .add("att1", att1)
    4. .add("att2", att2)
    5. .add("att3", att3)
    6. .add("super", super.toString()).toString();
    7. }
    8. // 使用JMH测出来的平均性能
    9. // (最小, 平均, 最大) = (97049,043, 110111,808, 114878,137)

    Commons Lang3
    Commons Lang3有一些技术来生成toString:从builder到 introspector。introspection更容易使用,代码量更少,但是性能比较糟糕:

    1. public String toString() {
    2. return new ToStringBuilder(this)
    3. .append("att1", att1)
    4. .append("att2", att2)
    5. .append("att3", att3)
    6. .append("super", super.toString()).toString();
    7. }
    8. // 使用JMH测出来的平均性能
    9. // (最小, 平均, 最大) = ( 73510,509, 75165,552, 76406,370)
    10. public String toString() {
    11. return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    12. }
    13. // 使用JMH测出来的平均性能
    14. // (最小, 平均, 最大) =(31803,224, 34930,630, 35581,488)
    15. public String toString() {
    16. return ReflectionToStringBuilder.toString(this);
    17. }
    18. // 使用JMH测出来的平均性能
    19. // (最小, 平均, 最大) = (14172,485, 23204,479, 30754,901)

    总结
    如今有了JVM优化,我们可以安全使用+来连接字符串(及使用Objects.toString来处理null)。有了内置到JDK的实用工具类,不需要外部框架来处理null值。
    微信图片_20210110230950.jpg