본문 바로가기

Java

[Java] Arrays.asList() 의 비밀

자바의 java.util.Arrays 클래스는 배열을 다루는 유용한 메서드들을 제공하는 클래스입니다. sort(), copyOf(), equals(), deepEquals(), fill() 등 여러 static 메서드가 포함되어 있습니다.

 

오늘은 이 중에서 배열을 List 로 변환해주는 asList() 메서드의 비밀에 대해 알아봅시다.

 

 

 

 

asList() 메서드의 구현은 아래와 같습니다.

 

@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T... a) {
	return new ArrayList<>(a);
}

 

보기엔 별 특이한 점이 없는 것 같은데요, 여기에는 아주 무시무시한 비밀이 숨겨져 있습니다.. 바로… 리턴하는 ArrayList 클래스가 Java Collections Framework 에 포함된 java.util.ArrayList 가 아니라, Arrays 클래스에 정의된 정적 클래스라는 점입니다..!! 알고 있었다면 유감입니다~ ^^;

 

 

암튼 이 Arrays$ArrayList 클래스는 다음과 같은 메서드들을 갖고 있습니다. (구현부 생략)

 

private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {

  private final E[] a;

  ArrayList(E[] array);

  public int size();

  public Object[] toArray();

  public <T> T[] toArray(T[] a);

  public E get(int index);

  public E set(int index, E element);

  public int indexOf(Object o);

  public boolean contains(Object o);
  
  public void replaceAll(UnaryOperator<E> operator);

  public void sort(Comparator<? super E> c);
}

 

Arrays$ArrayList 클래스에는 java.util.ArrayList 와는 달리, add(), remove() 메서드가 없습니다. 물론 AbstractList 클래스를 상속하고 있어서 .add() 를 붙일 순 있지만, UnsupportedOperationException 이 발생합니다. set() 메서드가 있긴 하지만 얘는 잠시 후 살펴보겠습니다.

 

  @Test
  void test() {
    String[] arr = {"A", "B", "C", "D", "E"};
    List<String> list = Arrays.asList(arr);

    assertThatThrownBy(() -> {
      list.add("F");
    }).isInstanceOf(UnsupportedOperationException.class);
  }

 

 

 

그럼 이렇게 Arrays.asList() 메서드가 Arrays 클래스 내부에 있는 static 클래스인 ArrayList 객체를 반환하도록 구현한 이유가 무엇일까요?

 

asList() 메서드의 의의는 배열을 갖고 완전히 새로운 리스트 객체를 만드는 것이 아닌, 기존 배열을 래핑(wrapping)한 리스트 객체를 생성하는 것에 있습니다. 생성된 ArrayList 는 입력된 배열을 래핑하고 있으므로, 원래 배열이 변경되면 리스트에도 역시 변경이 반영되고, 반대의 경우도 마찬가지입니다. 이렇게 함으로써 배열을 리스트로 사용하면서 얻을 수 있는 장점과 메모리 사용량이 줄어드는 장점을 모두 가지게 되는 것이죠.

 

 

따라서 아래 테스트 코드는 모두 성공하게 됩니다. list.set() 을 호출하면 list와 배열 모두 값이 변경되게 됩니다.

 

    String[] arr = {"A", "B", "C", "D", "E"};
    List<String> list = Arrays.asList(arr);
    
		list.set(0, "Z");

    assertThat(list.getFirst()).isEqualTo("Z");  // List.getFirst(): default 메서드
    assertThat(arr[0]).isEqualTo("Z");

    arr[1] = "Y";
    assertThat(list.get(1)).isEqualTo("Y");

 

 

이 요물같은 Arrays.asList() 메서드… 잘 알고 잘 써야겠습니다.^0^

 

 

 

 

 

Reference

https://docs.oracle.com/javase%2F7%2Fdocs%2Fapi%2F%2F/java/util/Arrays.html

https://www.baeldung.com/java-aslist-vs-singletonlist

'Java' 카테고리의 다른 글

[Java] Optional 때려 뿌수기  (5) 2023.10.31
[Java] Integer.valueOf("128")의 비밀  (2) 2023.03.10
[Java] Enum의 비교  (4) 2023.01.30
[Java] String Constant Pool  (1) 2022.04.02
[Java] Java Garbage Collection  (0) 2020.11.02