文字列Stringについて、注意すべき詳細


以前は、Javaプログラムを作成する際に、StringBuilderではなく、文字をつなぐときに「+」で実現していました.最近になって『Thinking in java』という本の文字列についての紹介を読んでやっと悟った!このようにするとかえって効率が低下し、プログラムが間違ってしまうこともあります.Stringについては、まずStringオブジェクトが可変であることを知っておく必要があります.可変とは何ですか?つまり、Stringのオブジェクトを変更するたびに新しいStringオブジェクトが作成され、変更された文字列が保存されます.これまでのStringの対象は少しも変わっていない.次のコードを見てみましょう.
public class Main {
    public static void main(String[] args) {
        String s = "java";
        System.out.println(s);
        String s1 = add(s);
        System.out.println(s1);
        System.out.println(s);
    }

    public static String add(String s) {
        return s + "8";
    }
}
出力内容:
java
java8
java
ここでは,タイムリーupcase()がs+"8"を返したことが分かるが,本来のsの値は変わらない.これは、Stringオブジェクトが可変ではないため、新しいオブジェクトが生成されたことを示すのに十分です.このメカニズムを理解した後、「+」とStringBuilderについて理解し、まず簡単なコードを見てみましょう.
public class Main {
    public static void main(String[] args) {
        String s = "abc";
        String s1 = s + "def" + "123" + "end";
        System.out.println(s1);
    }
}
前述したStringオブジェクトと組み合わせると可変であり、sに文字を追加するたびに新しいオブジェクトが生成されます.このように文字列をつなぎ合わせると、どれだけ使われていないオブジェクトが生成されるかがわかります.ごみ回収メカニズムはありますが、性能に影響します.実際には、コンパイラはこのコードをコンパイルするときにStringBuilderというクラスを「自業自得」に使用します.これは、より効率的になるからです.文字列をつなぎ合わせるたびにStringBuilderのappendメソッドが呼び出され、最終的にはtoString()として出力されます.直接接続文字列とStringBuilderクラスを使用して文字列を接続するのとでは、パフォーマンスにどのような違いがあるかを見てみましょう.
public class Main {
    public static void main(String[] args) {
        StringBuilder builder = new StringBuilder();
        String s = "scau";
        long start = System.currentTimeMillis();
        for (int i = 0; i < 2000; i++) {
            s += "hi";
        }
        System.out.println("          :" + (System.currentTimeMillis() - start));
        start = System.currentTimeMillis();
        builder.append("scau");
        for (int i = 0; i < 2000; i++) {
            builder.append("hi");
        }
        System.out.println("StringBuilder        :" + (System.currentTimeMillis() - start));
    }
}
出力結果:
          :16
StringBuilder        :0
このことから,StringBuilderの使用にはほとんど遅延がないことが分かる.最後に、「無意識再帰」について説明します.Stringオブジェクトの後にthisを追加すると、thisがStringオブジェクトではない場合、無限再帰の現象が発生し、java.lang.StackOverflowError異常が発生します.
public class Main {
    public static void main(String[] args) {
        System.out.println(new Scau().toString());
    }
}
class Scau {
    @Override
    public String toString() {
        return "scau" + this;
    }
}
「scau」+thisを返すと、thisはStringオブジェクトではないため、オブジェクトアドレス、すなわちtoString()メソッドを再呼び出し、無限再帰をもたらす...