注: この回答では、最新のランタイム JVM ライブラリに関連しない可能性のある例を使用しています。特に、このsubstring
例は OpenJDK/Oracle 7 以降では問題になりません。
人々がよく言うことに反することはわかっていますが、新しいString
インスタンスを明示的に作成すると、メモリを大幅に削減する場合があります。
文字列は不変であるため、いくつかのメソッドはその事実を利用し、バッキング文字配列を共有してメモリを節約します。ただし、場合によっては、これらの配列の未使用部分のガベージ コレクションを防止することで、実際にメモリを増やすことができます。
たとえば、ログ ファイルのメッセージ ID を解析して警告 ID を抽出しているとします。コードは次のようになります。
//Format:
//ID: [WARNING|ERROR|DEBUG] Message...
String testLine = "5AB729: WARNING Some really really really long message";
Matcher matcher = Pattern.compile("([A-Z0-9]*): WARNING.*").matcher(testLine);
if ( matcher.matches() ) {
String id = matcher.group(1);
//...do something with id...
}
しかし、実際に保存されているデータを見てください。
//...
String id = matcher.group(1);
Field valueField = String.class.getDeclaredField("value");
valueField.setAccessible(true);
char[] data = ((char[])valueField.get(id));
System.out.println("Actual data stored for string \"" + id + "\": " + Arrays.toString(data) );
マッチャーは同じ文字データを新しい String インスタンスでラップするだけなので、これはテスト行全体です。に置き換えたときの結果を比較しString id = matcher.group(1);
ますString id = new String(matcher.group(1));
。