Java 哪个toString()方法可以在性能方面使用?
我正在做一个项目来提高绩效。我有一个疑问,当我们在一个过程中,我们倾向于跟踪DTO和所用实体的当前状态。为此,我们在所有POJO中都包含了toString()方法。我现在以以下三种不同的方式实现了toString():-Java 哪个toString()方法可以在性能方面使用?,java,performance,Java,Performance,我正在做一个项目来提高绩效。我有一个疑问,当我们在一个过程中,我们倾向于跟踪DTO和所用实体的当前状态。为此,我们在所有POJO中都包含了toString()方法。我现在以以下三种不同的方式实现了toString():- public String toString() { return "POJO :" + this.class.getName() + " RollNo :" + this.rollNo + " Name :" + this.name; } public String
public String toString() {
return "POJO :" + this.class.getName() + " RollNo :" + this.rollNo + " Name :" + this.name;
}
public String toString() {
StringBuffer buff = new StringBuffer("POJO :").append(this.class.getName()).append(" RollNo :").append(this.rollNo).append(" Name :").append(this.name);
return buff.toString();
}
public String toString() {
StringBuilder builder = new StringBuilder("POJO :").append(this.class.getName()).append(" RollNo :").append(this.rollNo).append(" Name :").append(this.name);
return builder .toString();
}
谁能帮我找出哪一个是最好的,并且应该用于提高性能。使用第一个。我会解释原因的 天真的观点是使用最后一个。没有理由使用第二个。
StringBuffer
与StringBuilder
相同,只是它的性能受到synchronized
锁的影响。但不要把它放在一行上。这更具可读性:
public String toString() {
StringBuilder out = new StringBuilder(("POJO :");
out.append(this.getClass().getName());
out.append(" RollNo :");
out.append(this.rollNo);
out.append(" Name :");
out.append(this.name);
return out.toString();
}
也就是说,你必须小心这种微观优化。为什么?因为编译器通常会为您执行此操作。因此,编写最具可读性的内容,并让编译器对其进行优化
所以这里的主要教训是:不要进行微优化
但最终,你使用1或3中的哪一个可能并不重要
toString()
方法在应用程序中不会被大量使用。更常见的是,它们用于错误消息中,希望很少出现。在这种情况下,带有+
的错误消息就可以了。它更具可读性,而且与StringBuilder/StringBuffer
版本相比性能也一样,因为它“不会发生在循环内部”
如果要在循环中构建字符串
,则通常应使用StringBuilder
。如果您需要其同步
功能,请仅使用StringBuffer
,这种情况并不经常发生
简单地说(不一定是真的,但这是一个很好的经验法则),除非您使用字符串执行+=
,否则您并不真正需要StringBuilder/StringBuffer
相关问题
String.format
选项
一个经常不被考虑的选择是使用。它看起来像这样:
return String.format("POJO : %s RollNo %s : Name : %s",
this.getClass().getName(),
this.rollNo,
this.name
);
我发现这是最具可读性和可维护性的版本
这个快吗?也许是的,也许不是。对于像toString()
这样的常见用例场景,这通常并不重要。为可读性而努力,只有在分析认为有必要时才进行优化
API链接
关于类文字
我已将原始代码中的语法错误从this.class
(未编译)更正为this.getClass()
另见
相关问题
使用第一个,因为它更可读
但除此之外,这并不重要
- 在本例中使用
StringBuilder
和+
是等效的,因为编译器将重载的+
运算符转换为StringBuilder
StringBuffer
将较慢,因为它的方法是同步的,但由于编译器(在较新的版本中)可能会使用(更具体地说是同步省略),它将自动删除同步的
关键字。(请参阅以了解逃逸分析)
这在我看来更容易阅读
public String toString() {
return String.Format("POJO : {0} RollNo : {1} Name : {2}",
this.getClass().getName(),
this.rollNo,
this.name);
}
为什么要显式地使用StringBuilder呢?不管怎样,第一个表单都会隐式地使用一个,并且没有额外的错误。我知道编译器会将第一个版本转换为第三个版本,但是调试这个生成的版本是非常困难的,因为所发生的事情与您在源代码中看到的不一样,所以我倾向于使用第三个版本。@Seanizer您经常需要调试toString()方法吗?通常我会在toString中的一行上放置一个断点,并查看调试器中的变量值,它会告诉我可能导致异常的原因。@seanizer:您可以进一步理解该逻辑,并认为编写代码的唯一正确方法是在汇编中,因为这是“实际发生的”情况,对吗?不,我不同意。抽象是好的。忽视抽象是不好的,但抽象本身是好的。越多越好。@Peter,@Poly no我不经常调试toString方法,但我经常调试第三方库的方法,其中字符串连接发生在方法调用中,为了不错过我感兴趣的实际语句,我必须在eclipse中执行大量f5/f7操作。是的,抽象是好的,但在这种情况下,抽象的代价常常让我感到不安。汇编程序点是不相关的,因为幸运的是我的调试器没有单步执行汇编程序调用。但“发生了什么”这一措辞选择不当,我同意,我相信你可以在20分钟内写出一个基准。为什么要猜测何时可以进行测量?基准测试会显示结果,是的,但从理论上了解这些是很好的。可能重复“我正在进行一个项目以提高性能”-使用探查器,并确定代码的哪个部分实际上值得查看和优化。哇!哪个JVM运行时执行同步省略?这是我第一次听说这样一个(很酷!)功能@Polygene润滑油自JDK 6u14以来就可以使用,但我认为默认情况下不会启用。看看如何打开它。不要那么快。“不幸的是,在更新14中启用的基于escape分析的优化在更新18中再次被禁用,以便在将来某个日期重新恢复。”escape分析在6u20中存在,但我不知道它对该分析有什么作用,因为它似乎并没有加快速度。;)也许在C#中是这样,但在Java中不是这样。另外,this.class
没有编译。在java中,它的MessageFormat.format(…)具有相同的参数语法(实际上我会使用这个.getClass(),而不是getClass().getName(),不需要在需要之前对toString求值)。顺便说一句,this.class并不像很多人已经提到的那样编译“这更快吗?”-