Git :)

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Collections.unmodifiableMap 메소드를 이용한 read-only 객체 만들기
    Java 2025. 2. 19. 10:11

    웹 애플리케이션 기동 시 properties에 있는 설정 정보들을 컬렉션 객체에 저장하고 이를 가져다가 쓰는 경우가 많은데 이 객체에 변경을 막는 제약 조건을 걸고 싶을 때가 있다.

    즉, read-only 한 객체를 만들고 싶은 경우인데 이럴 때 다음의 메소드를 사용하면 좋을 것 같다.

     

    Collections.unmodifiableMap

    Collections.unmodifiableList

    해당 메소드는 파라미터로 전달 받은 컬렉션 객체에 어떠한 변경이라도 발생하면 예외를 return한다.

     

    테스트 코드는 다음과 같다.

    package collection;

     

    import static org.hamcrest.CoreMatchers.*;

    import static org.junit.Assert.*;

     

    import java.util.Collections;

    import java.util.HashMap;

    import java.util.Map;

     

    import org.junit.Test;

     

    public class CollectionsTest {

     

            @Test

            public void unmodifyMapTest() {

                   Map<Integer, String> testMap = new HashMap<Integer, String>();

                   testMap.put(1, "test1");

                   testMap.put(2, "test2");

     

                   Map<Integer, String> unmodifyTestMap = Collections.unmodifiableMap(testMap);

                   assertThat("test1", is(unmodifyTestMap.get(1)));

                   assertThat("test2", is(unmodifyTestMap.get(2)));

     

                   boolean exceptionThrown = false;

                   try {

                           unmodifyTestMap.put(3, "test3"); // unmodifyTestMap 객체 변경 시 예외

                   } catch (UnsupportedOperationException ex) {

                           ex.printStackTrace();

                           exceptionThrown = true;

                   }

     

                   assertTrue(exceptionThrown);

            }

    }

     

    문득 어떻게 해서 객체의 변경을 감지한 후 예외를 던지는지 궁금해 졌다.

     

    unmodifiableMap 메소드는 다음과 같은 구조를 가지고 있고, UnmodifiableMap 클래스의 타입을 return한다.

    public static <K,V> Map<K,V> unmodifiableMap(Map<? extends K, ? extends V> m) {

            return new UnmodifiableMap<K,V>(m);

    }

     

    자~ 그럼 UnmodifiableMap 클래스를 들여다 보자.

    Map 인터페이스를 구현한 UnmodifiableMap 클래스에서 put, remove, putAll 호출 시 UnsupportedOperationException 예외를 return하도록 설계되어 있다. (생각보다 간단하게 구현되어 있음. 역시 Java API)

    private static class UnmodifiableMap<K, V> implements Map<K, V>, Serializable {

            // use serialVersionUID from JDK 1.2.2 for interoperability

            private static final long serialVersionUID = -1034234728574286014L;

     

            private final Map<? extends K, ? extends V> m;

     

            UnmodifiableMap(Map<? extends K, ? extends V> m) {

                   if (m == null)

                           throw new NullPointerException();

                   this.m = m;

            }

     

            public int size() {

                   return m.size();

            }

     

            public boolean isEmpty() {

                   return m.isEmpty();

            }

     

            public boolean containsKey(Object key) {

                   return m.containsKey(key);

            }

     

            public boolean containsValue(Object val) {

                   return m.containsValue(val);

            }

     

            public V get(Object key) {

                   return m.get(key);

            }

     

            public V put(K key, V value) {

                   throw new UnsupportedOperationException();

            }

     

            public V remove(Object key) {

                   throw new UnsupportedOperationException();

            }

     

            public void putAll(Map<? extends K, ? extends V> m) {

                   throw new UnsupportedOperationException();

            }

     

            public void clear() {

                   throw new UnsupportedOperationException();

            }

    }