文字列結合の+演算子(2)
文字列結合の+演算子(1)のつづきです。
会社で識者の方にいろいろ話を聞いてみたところ、javacによる+演算子最適化の真骨頂は、リテラルの自動結合なんだそうです (下記参照)。逆に言えば、リテラルでない要素が含まれている場合は、あんまり嬉しくない状況になることもままあるようです。というのは、いくらString(Buffer|Builder)への変換が行われるとは言っても、この方々の持つ内部バッファであるchar配列の初期サイズはたったの16 (Sunの実装の場合) でしかありません。加算される要素の数と大きさ次第では、それこそ何度も何度も何度も何度も……配列確保 & 要素コピーが走ってしまうこともあり得るようです。おならぷー。
こういう時はやはり、コンストラクタで初期長を指定した上でString(Buffer|Builder)を手動で操作する方が良いようです。
javaコード
import java.util.*; public class test { public static void main(String[] args) { String a = "aaa" + "bbbb" + 9999 + "cccc" + 0xFFFF + "dddd"; System.out.println( a ); } }
逆コンパイル結果
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov. // Jad home page: http://www.kpdus.com/jad.html // Decompiler options: annotate fullnames lnc // Source File Name: test.java import java.io.PrintStream; public class test { public test() { /* 3*/ // 0 0:aload_0 /* 3*/ // 1 1:invokespecial #1 <Method void Object()> /* 3*/ // 2 4:return } public static void main(java.lang.String args[]) { /* 7*/ java.lang.String s = "aaabbbb9999cccc65535dddd"; /* 7*/ // 0 0:ldc1 #2 <String "aaabbbb9999cccc65535dddd"> /* 7*/ // 1 2:astore_1 /* 14*/ java.lang.System.out.println(s); /* 14*/ // 2 3:getstatic #3 <Field java.io.PrintStream java.lang.System.out> /* 14*/ // 3 6:aload_1 /* 14*/ // 4 7:invokevirtual #4 <Method void java.io.PrintStream.println(java.lang.String)> /* 15*/ // 5 10:return } }