String BufferとString Build学習ノート

4243 ワード

public class Concatenation {
  public static void main(String[] args) {
    String mango = "mango";
    String s = "abc" + mango + "def" + 47;
    System.out.println(s);
  }
} /* Output:
abcmangodef47
*///:~

「+」と「+=」オペレータはjavaに2つしかリロードされていないオペレータであることはよく知られています(javaではプログラマがオペレータをリロードすることは許可されていません).「+」はStringを接続するために使用できます.上記のコードに示すように.
このコードがどのように機能しているかはよく知られているかもしれませんが、プログラミング思想書の説明に従って、JDKが持参したツールjavapで上記のコードを逆コンパイルすることができます.コマンドは以下の通りです.javap-c Concatenationここの「-c」はJVMコードを生成することを示しています.走ってみると次のような結果になりました.
public class Concatenation {
  public Concatenation();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":
()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String mango
       2: astore_1
       3: new           #3                  // class java/lang/StringBuilder
       6: dup
       7: invokespecial #4                  // Method java/lang/StringBuilder."<
init>":()V
      10: ldc           #5                  // String abc
      12: invokevirtual #6                  // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      15: aload_1
      16: invokevirtual #6                  // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: ldc           #7                  // String def
      21: invokevirtual #6                  // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      24: bipush        47
      26: invokevirtual #8                  // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
      29: invokevirtual #9                  // Method java/lang/StringBuilder.to
String:()Ljava/lang/String;
      32: astore_2
      33: getstatic     #10                 // Field java/lang/System.out:Ljava/
io/PrintStream;
      36: aload_2
      37: invokevirtual #11                 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
      40: return
}

アセンブリ言語の経験がある人は見覚えがあるそうですが、ここのポイントはコンパイラがjavaを自動的に導入したことです.lang.StringBuilderクラスは、ソースコードはStringBuilderクラスを使用していませんが、コンパイラはより効率的に使用するため、勝手に使用しています.
StringBuilderはjava SE 5が導入したもので、ソースコードを見るとこのような注釈に気づきます
 * @author      Michael McCloskey
 * @see         java.lang.StringBuffer
 * @see         java.lang.String
 * @since       1.5
 */
public final class StringBuilder

since 1.5ですが、その前にjavaが何を使っていたのか、StringBufferです.
 * @author      Arthur van Hoff
 * @see     java.lang.StringBuilder
 * @see     java.lang.String
 * @since   JDK1.0
 */
 public final class StringBuffer

1.0はすでにあり、スレッドが安全なので、オーバーヘッドも大きいのでjava SE 5/6(現在は8になっています)では、文字列の操作はもっと速くなるはずです.
ソースコードを見ると、注釈の最初の文がスレッドが安全かどうかを説明していることがわかります.
/*
 * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.lang;

import java.util.Arrays;

/**
 * A thread-safe, mutable sequence of characters.
 * A string buffer is like a {@link String}, but can be modified. At any
 * point in time it contains some particular sequence of characters, but
 * the length and content of the sequence can be changed through certain
 * method calls.

ソースコードを見ると、StringBufferクラスの多くの方法はsynchronizedキーワードで宣言されていますが、StringBuilderにはありません.StringBuilderは非スレッドセキュリティです.
StringBufferとStringBuilderの親はAbstractStringBuilderであり、それらの構築方法はすべて親を呼び出す構築方法である
/**
     * Constructs a string buffer with no characters in it and an
     * initial capacity of 16 characters.
     */
    public StringBuffer() {
        super(16);
    }
  /**
     * Constructs a string builder with no characters in it and an
     * initial capacity of 16 characters.
     */
    public StringBuilder() {
        super(16);
    }
    /**
     * Creates an AbstractStringBuilder of the specified capacity.
     */
    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }