首先让我们一起看看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值不会被处理,需要自己来处理它。
public String toString() {return "MyObject{" +"att1='" + att1 + ''' +", att2='" + att2 + ''' +", att3='" + att3 + ''' +"} " + super.toString();}// 使用JMH测出来的平均性能// (最小, 平均, 最大) = (140772,314, 142075,167, 143844,717)
用Objects.toString连接字符串
Java SE 7带来了Objects类和它的一些静态方法。Objects.toString的优点是它可以处理null值,甚至可以给null设置默认值。其性能与上一个相比略低,但是null值可以被处理:
public String toString() {return "MyObject{" +"att1='" + Objects.toString(att1) + ''' +", att2='" + Objects.toString(att2) + ''' +", att3='" + Objects.toString(att3) + ''' +"} " + super.toString();}// 使用JMH测出来的平均性能// (最小, 平均, 最大) = (138790,233, 140791,365, 142031,847)
StringBuilder
另一种技术是使用StringBuilder。
public String toString() {final StringBuilder sb = new StringBuilder("MyObject{");sb.append("att1='").append(att1).append(''');sb.append(", att2='").append(att2).append(''');sb.append(", att3='").append(att3).append(''');sb.append(super.toString());return sb.toString();}// 使用JMH测出来的平均性能// (最小, 平均, 最大) = (96073,645, 141463,438, 146205,910)
Guava
Guava有一些helper类:其中一个可以帮助你生成toString。
public String toString() {return Objects.toStringHelper(this).add("att1", att1).add("att2", att2).add("att3", att3).add("super", super.toString()).toString();}// 使用JMH测出来的平均性能// (最小, 平均, 最大) = (97049,043, 110111,808, 114878,137)
Commons Lang3
Commons Lang3有一些技术来生成toString:从builder到 introspector。introspection更容易使用,代码量更少,但是性能比较糟糕:
public String toString() {return new ToStringBuilder(this).append("att1", att1).append("att2", att2).append("att3", att3).append("super", super.toString()).toString();}// 使用JMH测出来的平均性能// (最小, 平均, 最大) = ( 73510,509, 75165,552, 76406,370)public String toString() {return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);}// 使用JMH测出来的平均性能// (最小, 平均, 最大) =(31803,224, 34930,630, 35581,488)public String toString() {return ReflectionToStringBuilder.toString(this);}// 使用JMH测出来的平均性能// (最小, 平均, 最大) = (14172,485, 23204,479, 30754,901)
总结
如今有了JVM优化,我们可以安全使用+来连接字符串(及使用Objects.toString来处理null)。有了内置到JDK的实用工具类,不需要外部框架来处理null值。
