Language
String pool: リテラルとnew Stringは参照共有が違う
同じStringリテラルはpoolの参照を共有し得ますが、new Stringは別インスタンスを作ります。
SourceStringReferences.java
Java 21
package examples.stringpool;
public final class StringReferences {
private StringReferences() {}
public static boolean literalsShareReference() {
String first = "java";
String second = "java";
return first == second;
}
public static boolean newStringSharesReference() {
return "java" == new String("java");
}
public static boolean internedStringSharesReference() {
return "java" == new String("java").intern();
}
}TestStringReferencesTest.java
Java 21
package examples.stringpool;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
class StringReferencesTest {
@Test
void 同じリテラルはpoolの同じ参照を共有する() {
assertTrue(StringReferences.literalsShareReference());
}
@Test
void newStringは同じ内容でも別の参照を作る() {
assertFalse(StringReferences.newStringSharesReference());
}
@Test
void internはpool内の参照を返す() {
assertTrue(StringReferences.internedStringSharesReference());
}
}01Assertion
このテストで確認できること
- 同じリテラルは==で同じ参照になる
- new Stringは別参照、internはpoolの参照を返す
poolの共有は値比較に==を使ってよい理由にはなりません。Stringの比較は常にequalsを選び、参照共有は実装上の性質として扱います。
OBSERVED RESULT
literal == literal → true
literal == new String → false
literal == interned → true