Java 添加一个空字符串vs toString-为什么它不好?
根据PMD工具,以下为不良做法:Java 添加一个空字符串vs toString-为什么它不好?,java,string,tostring,pmd,Java,String,Tostring,Pmd,根据PMD工具,以下为不良做法: String s = "" + 123; // bad String t = Integer.toString(456); // ok This is an inefficient way to convert any type to a `String`. 为什么这样做是一件坏事?它扩展到“+String.valueOf(yourObject)”,因此进行了不必要的连接。连接包括分配一个额外的字符串并对字符串的值进行额外的复制。这是低效的,因为它涉及
String s = "" + 123; // bad
String t = Integer.toString(456); // ok
This is an inefficient way to convert any type to a `String`.
为什么这样做是一件坏事?它扩展到“+String.valueOf(yourObject)”,因此进行了不必要的连接。连接包括分配一个额外的字符串并对字符串的值进行额外的复制。这是低效的,因为它涉及一个不必要的字符串连接,因此创建一个或两个额外的
string
对象-尽管我相信JIT可以优化它
对我来说,更大的问题是代码不够清晰。调用toString
是一种标准的习惯用法,每个Java开发人员都能理解(希望:-),所以您应该更喜欢这样
String s = "" + 123; // bad
String t = Integer.toString(456);
将汇编为:
String s = "123";
String t = Integer.toString(456);
所以:“+123显然稍微好一点已检查
publicstaticvoidmain(字符串参数[])
{
//0:ldc1#16
//12:astore_1
//23:sipush 456
//36:invokestatic#18
//4.9:astore_2
//5 10:getstatic#24
//6 13:新#30
//7 16:dup
//8 17:aload_1
//9 18:invokestatic#32
//10 21:38
//11 24:aload_2
//12 25:invokevirtual#41
//13 28:invokevirtual#45
//14 31:invokevirtual#48
//15 34:返回
}
编辑:
对于非常量值:
int i = 123;
String s = (new StringBuilder()).append(i).toString();
String t = Integer.toString(i);
System.out.println((new StringBuilder(String.valueOf(s))).append(t).toString());
public static void main(String args[])
{
// 0 0:bipush 123
// 1 2:istore_1
// 2 3:new #16 <Class StringBuilder>
// 3 6:dup
// 4 7:invokespecial #18 <Method void StringBuilder()>
// 5 10:iload_1
// 6 11:invokevirtual #19 <Method StringBuilder StringBuilder.append(int)>
// 7 14:invokevirtual #23 <Method String StringBuilder.toString()>
// 8 17:astore_2
// 9 18:iload_1
// 10 19:invokestatic #27 <Method String Integer.toString(int)>
// 11 22:astore_3
// 12 23:getstatic #32 <Field PrintStream System.out>
// 13 26:new #16 <Class StringBuilder>
// 14 29:dup
// 15 30:aload_2
// 16 31:invokestatic #38 <Method String String.valueOf(Object)>
// 17 34:invokespecial #44 <Method void StringBuilder(String)>
// 18 37:aload_3
// 19 38:invokevirtual #47 <Method StringBuilder StringBuilder.append(String)>
// 20 41:invokevirtual #23 <Method String StringBuilder.toString()>
// 21 44:invokevirtual #50 <Method void PrintStream.println(String)>
// 22 47:return
}
inti=123;
字符串s=(新的StringBuilder()).append(i).toString();
字符串t=整数。toString(i);
System.out.println((新的StringBuilder(String.valueOf)).append(t.toString());
公共静态void main(字符串参数[])
{
//0:bipush 123
//1.2:istore_1
//2 3:新#16
//36:dup
//4.7:特别是
//5 10:iload_1
//6 11:invokevirtual#19
//7 14:invokevirtual#23
//8 17:astore_2
//9 18:iload_1
//10 19:invokestatic#27
//11 22:astore_3
//12 23:getstatic#32
//13 26:新#16
//14:29:dup
//15 30:aload_2
//16 31:invokestatic#38
//17 34:特别是
//18 37:aload_3
//19 38:invokevirtual#47
//20 41:invokevirtual#23
//21 44:invokevirtual#50
//22 47:返回
}
上面的代码创建了一个临时字符串,将“”和123组合在一起,而tostring版本清楚地说明了这一意图。“将此值转换为字符串”从代码生成的角度来看,这并不是严格正确的,因此我将避免使用向上投票。它实际上(对于我测试过的Java 6u20)扩展为:
new StringBuilder().append(“”).append(yourObject).toString()
,假设yourObject
不是常量。我不确定我是否在跟踪你。你证明了“+123”比Integer.toString(123)好吗?实际检查是+1。那么,对象类型而不是pod类型呢?“+123是一个常量表达式,编译器已经将其评估为“123”。@stacker:“因此:“+123明显稍微好一些”更好是主观的,唯一明显的是它更快。为了性能而牺牲可读性,没有已知的性能问题,过早的优化通常被认为是错误的。我认为,将此标记为答案是误导和无益的。正如Chris Jester Young指出的,只有在int为final的情况下,它才会更快。为了生成更好的代码,在int为final的情况下,应该将该int对应的字符串表示为也是final的字符串(这是编译器自动执行的操作)“+123
一点也不“更好”,它相当于用值声明一个新的静态字符串“123”
,与int123
无关。显然,对于常量(静态/最终)”“+123更有效。对于其他值,使用toString更有效。“Static/final”可能会产生误导。字段必须是静态的和最终的,才能被视为常量,并且仅适用于原语和字符串。(局部变量从不被认为是常数。)可能的重复不是那么简单。见斯塔克的答案。如果不是123,而是一个非常量值,那么你是正确的。代码透明性对我来说是至关重要的。代码清晰性应该始终先于微观优化。
int i = 123;
String s = (new StringBuilder()).append(i).toString();
String t = Integer.toString(i);
System.out.println((new StringBuilder(String.valueOf(s))).append(t).toString());
public static void main(String args[])
{
// 0 0:bipush 123
// 1 2:istore_1
// 2 3:new #16 <Class StringBuilder>
// 3 6:dup
// 4 7:invokespecial #18 <Method void StringBuilder()>
// 5 10:iload_1
// 6 11:invokevirtual #19 <Method StringBuilder StringBuilder.append(int)>
// 7 14:invokevirtual #23 <Method String StringBuilder.toString()>
// 8 17:astore_2
// 9 18:iload_1
// 10 19:invokestatic #27 <Method String Integer.toString(int)>
// 11 22:astore_3
// 12 23:getstatic #32 <Field PrintStream System.out>
// 13 26:new #16 <Class StringBuilder>
// 14 29:dup
// 15 30:aload_2
// 16 31:invokestatic #38 <Method String String.valueOf(Object)>
// 17 34:invokespecial #44 <Method void StringBuilder(String)>
// 18 37:aload_3
// 19 38:invokevirtual #47 <Method StringBuilder StringBuilder.append(String)>
// 20 41:invokevirtual #23 <Method String StringBuilder.toString()>
// 21 44:invokevirtual #50 <Method void PrintStream.println(String)>
// 22 47:return
}
String s = "" + 123; // bad