Java - unmodifiableCollection은 불변성을 완벽히 보장하나요?

Tae Yun Choi·2023년 4월 17일
0

개발새발 Java

목록 보기
3/4
post-thumbnail
💡 불변성을 보장하기 위해 사용되는 unmodifiableList에 대해 알아보자

final은 Colletion의 불변성을 보장할 수 없다.

  • final 키워드는 재할당을 막는 키워드이지, 불변성을 보장해주지 않는다.
final <List list = new ArrayList();
list.add(1)
// [1]
// 잘 실행된다.

이러한 이유로 unmodifiableList를 사용한다.

  • unmodifiableList는 Collection의 add, set과 같이 collection의 수정을 일으키는 메서드들을 호출할 수 없게 만든다.
  • 해당 메소드를 사용시 UnsupportOperationException을 발생시킨다
  • 다음 사진은 unmodifiableCollection 클래스 하위에 구현되어있는 Method들이다.

하지만 여기에는 함정이 있다.

  • 바로 원본 객체와 연결이 끊기고, 새로운 배열을 복사해서 할당해주는 것은 아니라는 점이다.
List list = new ArrayList(Arrays.asList(1, 2, 3));
List unmodifiableList = Collections.unmodifiableList(list);

list.add(4);

System.out.println(list); // [1, 2, 3, 4]
System.out.println(unmodifiableList); // [1, 2, 3, 4]
  • 해당 코드를 실행 시 원본 리스트에 추가한 4가 unmodifiableList에도 추가된 것을 확인할 수 있다.
  • 즉, Collections.unmodifiableCollection의 리턴 객체는 add, set과 같은 메서드를 사용할 수 없도록 Collection 인터페이스를 구현한 구현체일 뿐이다.
  • 다음과 같이 멤버변수에 할당연산자를 통해 그냥 주소값을 할당하고 있을 뿐이므로, 원본 객체와의 연결이 끊기는 것은 아니다.

그러면 어떻게 해야할까?

  • 바로 unmodifiableCollection을 생성할 때 직접 복사하여 새로운 객체를 넣어주는 방법을 사용하면 원본객체의 수정에도 영향을 받지 않게 된다.
List list = new ArrayList(Arrays.asList(1, 2, 3));
List unmodifiableList = Collections.unmodifiableList(new ArrayList<>(list));

list.add(4);

System.out.println(list); // [1, 2, 3, 4]
System.out.println(unmodifiableList); //[1, 2, 3]
  • 위 코드를 실행하면 더 이상 원본객체의 수정에 영향을 받지 않는 것을 볼 수 있다.

추가적으로

  • List.of() 메소드 활용 (JDK 9+)
  • record 데이터 클래스 활용 (JDK 14+)

출처

profile
hello dev!!

0개의 댓글