Collections
Collections: unmodifiable view と immutable copy は共有状態が違う
unmodifiable view は元のListを読み続け、List.copyOfの結果は作成時点の独立した値です。
SourceListSnapshots.java
Java 21
package examples.collectionviews;
import java.util.Collections;
import java.util.List;
public final class ListSnapshots {
private ListSnapshots() {}
public static List<String> unmodifiableView(List<String> values) {
return Collections.unmodifiableList(values);
}
public static List<String> immutableCopy(List<String> values) {
return List.copyOf(values);
}
}TestListSnapshotsTest.java
Java 21
package examples.collectionviews;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Test;
class ListSnapshotsTest {
@Test
void unmodifiableViewは元のListの後続変更を反映する() {
var source = new ArrayList<>(List.of("A"));
var view = ListSnapshots.unmodifiableView(source);
source.add("B");
assertEquals(List.of("A", "B"), view);
assertThrows(UnsupportedOperationException.class, () -> view.add("C"));
}
@Test
void immutableCopyは元のListの後続変更を反映しない() {
var source = new ArrayList<>(List.of("A"));
var copy = ListSnapshots.immutableCopy(source);
source.add("B");
assertEquals(List.of("A"), copy);
}
}01Assertion
このテストで確認できること
- unmodifiable viewは元のListへの変更を反映する
- immutable copyは元のListへの後続変更を反映しない
変更できないことと、状態を共有しないことは別の契約です。スナップショットが必要ならunmodifiableListではなくコピーを作ります。
OBSERVED RESULT
view after source.add → [A, B]
copy after source.add → [A]