5

小さなマイクロベンチマーク アプリ (JDK 1.6 を実行) には、次の 2 つの方法があります。

public static String testStringBuilder3(String str1, String str2, String str3, String str4, String str5) {
    return new StringBuilder(str1).append("-").append(str2).append("-").append(str3).append("-").append(str4).append("-").append(str5).toString();
}

public static String testStringBuilder4(String str1, String str2, String str3, String str4, String str5) {
    return str1 + "-" + str2 + "-" + str3 + "-" + str4 + "-" + str5;
}

これら 2 つのメソッドのバイトコードは同一であることが期待されます。それらはほとんど同じですが、私が理解したい小さな違いが 1 つあります。

最初のメソッドのバイトコードは次のとおりです (これを正しくフォーマットするために StackOverflow を取得できません)。

public static java.lang.String testStringBuilder3(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
Code:
  0:    new #164; //class java/lang/StringBuilder
  3:    dup
  4:    aload_0
  5:    invokespecial   #170; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  8:    ldc #182; //String -
 10:    invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 13:    aload_1
 14:    invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 17:    ldc #182; //String -
 19:    invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 22:    aload_2
 23:    invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 26:    ldc #182; //String -
 28:    invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 31:    aload_3
 32:    invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 35:    ldc #182; //String -
 37:    invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 40:    aload   4
 42:    invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
 45:    invokevirtual   #176; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
 48:    areturn

2 番目のメソッドのバイトコードは次のとおりです。

public static java.lang.String testStringBuilder4(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
Code:
  0:    new #164; //class java/lang/StringBuilder
  3:    dup
  4:    aload_0
  5:    invokestatic    #166; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
  8:    invokespecial   #170; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  11:   ldc #182; //String -
  13:   invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  16:   aload_1
  17:   invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  20:   ldc #182; //String -
  22:   invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  25:   aload_2
  26:   invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  29:   ldc #182; //String -
  31:   invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  34:   aload_3
  35:   invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  38:   ldc #182; //String -
  40:   invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  43:   aload   4
  45:   invokevirtual   #172; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  48:   invokevirtual   #176; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  51:   areturn

2 つの唯一の違いは、2 番目の方法の次のバイトコード行です。

   5:   invokestatic    #166; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;

それは何をしているのでしょうか?

4

1 に答える 1

5

JDK ソースから:

public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

最初の変数が null でないことを確認しています。それ以外の場合は、 がスローNullPointerExceptionされます。StringBuilder(String str)

例:

public class StringTest
{
  public static void main(String a[])
  {
    System.out.println(testStringBuilder3(null, null, null, null, null));
    System.out.println(testStringBuilder4(null, null, null, null, null));
  }
 public static String testStringBuilder3(String str1, String str2, String str3, String str4, String str5) {
    return str1 + "-" + str2 + "-" + str3 + "-" + str4 + "-" + str5;
  }
  public static String testStringBuilder4(String str1, String str2, String str3, String str4, String str5) {
    return new StringBuilder(str1).append("-").append(str2).append("-").append(str3).append("-").append(str4).append("-").append(str5).toString();
  }
}

出力:

null-null-null-null-null
Exception in thread "main" java.lang.NullPointerException
    at java.lang.StringBuilder.<init>(Unknown Source)
    at StringTest.testStringBuilder3(StringTest.java:15)
    at StringTest.main(StringTest.java:11)
于 2013-05-03T17:07:32.363 に答える