String valueOf vs与空字符串连接

Coo*_*חמד 48 java

我正在从事Java代码优化.我不清楚之差String.valueOf的或+""标志:

int intVar = 1;
String strVar = intVar + "";
String strVar = String.valueOf(intVar);
Run Code Online (Sandbox Code Playgroud)

第2行和第3行有什么区别?

Jig*_*shi 63

public void foo(){
int intVar = 5;
String strVar = intVar+"";    
}
Run Code Online (Sandbox Code Playgroud)

此方法使用StringBuilder创建结果String

public void foo();
  Code:
   0:   iconst_5
   1:   istore_1
   2:   new     #2; //class java/lang/StringBuilder
   5:   dup
   6:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
   9:   iload_1
   10:  invokevirtual   #4; //Method java/lang/StringBuilder.append:(I)Ljava/lan
g/StringBuilder;
   13:  ldc     #5; //String
   15:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(Ljava/lang/
String;)Ljava/lang/StringBuilder;
   18:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/la
ng/String;
   21:  astore_2
   22:  return
Run Code Online (Sandbox Code Playgroud)
public void bar(){
int intVar = 5;
String strVar = String.valueOf(intVar);
}
Run Code Online (Sandbox Code Playgroud)

这种方法只调用一个静态方法String来获取int的String版本

public void bar();
  Code:
   0:   iconst_5
   1:   istore_1
   2:   iload_1
   3:   invokestatic    #8; //Method java/lang/String.valueOf:(I)Ljava/lang/Stri
ng;
   6:   astore_2
   7:   return
Run Code Online (Sandbox Code Playgroud)

反过来打电话 Integer.toString()

  • 这并没有告诉我们,JIT编译器是否会(尤其是)将第一个版本优化为更简单的形式。 (2认同)
  • 那么哪个更好呢? (2认同)

Jon*_*eet 24

问问自己代码的目的.它是:

  • 使用值连接空字符串
  • 将值转换为字符串

听起来更像是后者......这就是我使用的原因String.valueOf.每当你能够以与描述想要实现的目标相同的方式阅读代码时,这是一件好事.

请注意,这适用于所有类型,并且在传递空引用时返回"null"而不是抛出a NullPointerException.如果你正在使用一个类(不是int在这个例子中),并且你希望它抛出一个异常,如果它是null(例如因为它代表一个bug),请调用toString引用.

  • `String.valueOf(int x)`*只调用String的静态方法来获取int*的String版本.当我们谈论Android时,建议*避免*使用静态方法.您如何看待Android中的这种方法? (3认同)

duf*_*ymo 9

我更喜欢valueOf(),因为我认为它更具可读性和显性.

对性能的任何担忧都是微观优化,无法衡量.在我能够进行测量并发现它们有所作为之前,我不会担心它们.


Pet*_*rey 7

使用String.valueOf(int)或更好Integer.toString(int)地对机器来说相对更有效.但是,除非性能至关重要(在这种情况下我不建议你使用)然后""+ x更有效地利用你的时间.恕我直言,这通常更重要.有时候更重要的是.

换句话说,""+浪费一个对象,但Integer.toString()无论如何都会产生几个.要么您的时间更重要,要么不想不惜一切代价避免创建对象.您极不可能处于创建多个对象的位置,但创建一个对象则不然.


Jit*_*ngh 7

好吧,如果你查看 JRE 源代码,Integer.getChars(...)就会发现最重要的方法实际上执行从整数到 char[] 的转换,但它是一个包私有方法。
所以问题是如何以最小的开销调用这个方法。
以下是通过跟踪对目标方法的调用来概述这 3 种方法,请查看 JRE 源代码以更好地理解这一点。

  1. "" + intVar编译为:
    new StringBuilder()=> StringBuilder.append(int)=>Integer.getChars(...)
  2. String.valueOf(intVar)=> Integer.toString(intVar)=>Integer.getChars(...)
  3. Integer.toString(intVar)=>Integer.getChars(...)

第一种方法不必要地创建一个额外的对象,即 StringBuilder。
第二个方法只是委托给第三个方法。
所以你现在就有答案了。

PS:各种编译时和运行时优化在这里发挥作用。因此,实际的性能基准可能会根据不同的 JVM 实现而有所不同,而这是我们无法预测的,所以我通常更喜欢通过查看源代码看起来高效的方法。


Thi*_*ilo 5

第一行相当于

String strVal = String.valueOf(intVar) + "";
Run Code Online (Sandbox Code Playgroud)

这样就有一些额外的(而且毫无意义的)工作要做。不确定编译器是否优化了与空字符串文字的连接。如果没有(并且看看@Jigar的答案,它显然没有),这将反过来变成

String strVal = new StringBuilder().append(String.valueOf(intVar))
                      .append("").toString();
Run Code Online (Sandbox Code Playgroud)

所以你真的应该直接使用 String.valueOf 。