メソッドがあるとします:
public String getString() {
char[] array = new char[]{'a', 'b', 'c'};
return new String(array);
}
配列は引き続き String コンストラクターでコピーされますか?それとも Java コンパイラーは、配列内の要素が変更できないことを認識して、配列を参照するだけでよいのでしょうか?
ありがとう
メソッドがあるとします:
public String getString() {
char[] array = new char[]{'a', 'b', 'c'};
return new String(array);
}
配列は引き続き String コンストラクターでコピーされますか?それとも Java コンパイラーは、配列内の要素が変更できないことを認識して、配列を参照するだけでよいのでしょうか?
ありがとう
JavaString
クラスは不変であるため、コンストラクターは配列をコピーする必要があります。
それ以外の場合は、誰かが配列への参照を保持して変更できます。
char[] array = new char[]{'a', 'b', 'c'};
String string = new String(array);
array[1] = 'd'; // array modification must NOT affect the string
のソースを参照してくださいjava.lang.String
:
/**
* Allocates a new {@code String} so that it represents the sequence of
* characters currently contained in the character array argument. The
* contents of the character array are copied; subsequent modification of
* the character array does not affect the newly created string.
*
* @param value
* The initial value of the string
*/
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
編集:
java.util.Arrays
which 呼び出しのソースも参照してくださいSystem.arraycopy
。
答えは明らかです。String
不変のままであるためには、防御的に配列をコピーする必要があります。
次のコードを検討してください。
public String getString() {
char[] array = new char[]{'a', 'b', 'c'};
String s = new String(array); // abc
array[0] = 'x';
return s; // xbc
}
配列がコピーされていない場合、バッキング配列がリークされ、文字列が可変性にさらされます。
このコンストラクターも見てください。
153 public String(String original) {
154 this.value = original`.value;
155 this.hash = original.hash;
156 }
これは文字列リテラルになります。
"abc"
String(char[] value)
これは、char 配列の要素として渡された a、b、c を使用した単なる呼び出しです。要するに、String x = "abc"
上記の処理を回避するためにコンパイラが提供する単なる構文糖衣です。
ソースコードを見れば答えが出ます。入力配列はコピーされ、参照されません。ソースコードは次のとおりです。
public String(char value[]) {
this.offset = 0;
this.count = value.length;
this.value = StringValue.from(value);
}
static char[] from(char[] value) {
return Arrays.copyOf(value, value.length);
}