java 원본 분석 Arrays.asList 메소드 상세 정보

최근에 짬을 내서 자바 Arrays 도구류의 asList 방법을 원본 분석하여 인터넷에서 관련 자료를 정리하고 기록하여 독자들에게 도움이 되었으면 합니다!
Arrays 도구 클래스는 asList를 제공합니다. 이 방법을 사용하면 긴 매개 변수나 그룹을 List로 변환할 수 있습니다.
소스 코드는 다음과 같습니다.

 /**
  * Returns a fixed-size list backed by the specified array. (Changes to
  * the returned list "write through" to the array.) This method acts
  * as bridge between array-based and collection-based APIs, in
  * combination with {@link Collection#toArray}. The returned list is
  * serializable and implements {@link RandomAccess}.
  *
  * <p>This method also provides a convenient way to create a fixed-size
  * list initialized to contain several elements:
  * <pre>
  *  List&lt;String&gt; stooges = Arrays.asList("Larry", "Moe", "Curly");
  * </pre>
  *
  * @param a the array by which the list will be backed
  * @return a list view of the specified array
  */
 @SafeVarargs
 public static <T> List<T> asList(T... a) {
  return new ArrayList<>(a);
 }
 

문제 발견
상기 방법의 설명에 근거하여 우리는 먼저 몇 가지 예를 작성한다.

/**
 * @author wangmengjun
 *
 */
public class ArrayExample {
 
 public static void main(String[] args) {
  
  /** */
  List<String> array1 = Arrays.asList("Welcome", "to","Java", "world");
  System.out.println(array1);
  
  /** */
  List<String> array2 = Arrays.asList(new String[] {"Welcome", "to","Java", "world"});
  System.out.println(array2);
 }

}

상기 프로그램을 실행하면 다음과 같은 내용을 출력합니다.
[Welcome, to, Java, world]
[Welcome, to, Java, world]
심혈을 기울여 만든 목록에 "Cool~~~"문자열을 추가하고 싶습니다.

 /** */
  List<String> array1 = Arrays.asList("Welcome", "to","Java", "world");
  array1.add("Cool~~~");
결과적으로 지원되지 않는 OperationException 예외가 발생했습니다.

Exception in thread "main" java.lang.UnsupportedOperationException
 at java.util.AbstractList.add(Unknown Source)
 at java.util.AbstractList.add(Unknown Source)
 at test.ArrayExample.main(ArrayExample.java:36)
놀랍게도 new ArrayList<>(a)에서 생성된 목록은add 방법을 호출하는데 문제가 발생했습니다.
원인 찾기
그럼 문제가 생겼어요. 도대체 무슨 일이 일어난 거예요?의문을 가지고 Arrays를 확인해 보세요.AS List에 사용된 Array List는 어떻게 생겼습니까?
원래 Arrays의 asList 방법에 사용된 ArrayList 클래스는java가 아니라 내부적으로 정의된 클래스입니다.util.Array List 클래스.
소스 코드는 다음과 같습니다.

 /**
   * @serial include
   */
  private static class ArrayList<E> extends AbstractList<E>
    implements RandomAccess, java.io.Serializable
  {
    private static final long serialVersionUID = -2764017481108945198L;
    private final E[] a;

    ArrayList(E[] array) {
      if (array==null)
        throw new NullPointerException();
      a = array;
    }

    public int size() {
      return a.length;
    }

    public Object[] toArray() {
      return a.clone();
    }

    public <T> T[] toArray(T[] a) {
      int size = size();
      if (a.length < size)
        return Arrays.copyOf(this.a, size,
                   (Class<? extends T[]>) a.getClass());
      System.arraycopy(this.a, 0, a, 0, size);
      if (a.length > size)
        a[size] = null;
      return a;
    }

    public E get(int index) {
      return a[index];
    }

    public E set(int index, E element) {
      E oldValue = a[index];
      a[index] = element;
      return oldValue;
    }

    public int indexOf(Object o) {
      if (o==null) {
        for (int i=0; i<a.length; i++)
          if (a[i]==null)
            return i;
      } else {
        for (int i=0; i<a.length; i++)
          if (o.equals(a[i]))
            return i;
      }
      return -1;
    }

    public boolean contains(Object o) {
      return indexOf(o) != -1;
    }
  }
이 내부 클래스 Array List의 실현을 통해 알 수 있듯이 추상적인 클래스java를 계승했다.util.AbstractList, 그러나add와remove 방법을 다시 쓰지 않고 구체적인 실현을 제시하지 않았습니다.
단, 기본적으로 자바.util.AbstractList 클래스는add,set 및remove 방법에서 지원되지 않는 OperationException 이상을 직접 던집니다.AbstractList의 일부 소스 코드는 다음과 같습니다.

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {
  /**
   * Sole constructor. (For invocation by subclass constructors, typically
   * implicit.)
   */
  protected AbstractList() {
  }

  public E set(int index, E element) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   *
   * <p>This implementation always throws an
   * {@code UnsupportedOperationException}.
   *
   * @throws UnsupportedOperationException {@inheritDoc}
   * @throws ClassCastException      {@inheritDoc}
   * @throws NullPointerException     {@inheritDoc}
   * @throws IllegalArgumentException   {@inheritDoc}
   * @throws IndexOutOfBoundsException   {@inheritDoc}
   */
  public void add(int index, E element) {
    throw new UnsupportedOperationException();
  }

  /**
   * {@inheritDoc}
   *
   * <p>This implementation always throws an
   * {@code UnsupportedOperationException}.
   *
   * @throws UnsupportedOperationException {@inheritDoc}
   * @throws IndexOutOfBoundsException   {@inheritDoc}
   */
  public E remove(int index) {
    throw new UnsupportedOperationException();
  }
}

바로 자바 때문이야.util.Arrays 클래스의 내부 클래스인 ArrayList는add와remove 방법을 다시 쓰지 않았기 때문에 우리가add 방법을 호출할 때 사실은 AbstractList 클래스의add 방법을 호출한 것이다. 결과는 바로 UnsupportedOperationException 이상을 던지는 것이다.
같은 이치로,remove 방법을 호출하거나,add,remove 방법과 관련된 다른 방법 (예:addAll) 을 호출하면 UnsupportedOperationException 이상을 만날 수 있습니다.
addAll의 예:

/**
 * @author wangmengjun
 *
 */
public class ArrayExample {

  public static void main(String[] args) {

    /** */
    List<String> array1 = Arrays.asList("Welcome", "to", "Java", "world");
    array1.addAll(Arrays.asList("AAA", "BBB"));
  }

}


Exception in thread "main" java.lang.UnsupportedOperationException
 at java.util.AbstractList.add(Unknown Source)
 at java.util.AbstractList.add(Unknown Source)
 at java.util.AbstractCollection.addAll(Unknown Source)
 at test.ArrayExample.main(ArrayExample.java:36)
 

set 예:

/**
 * @author wangmengjun
 *
 */
public class ArrayExample {

  public static void main(String[] args) {

    /** */
    List<String> array1 = Arrays.asList("Welcome", "to", "Java", "world");
    System.out.println(array1);
    
    // Java hello
    array1.set(2, "hello");
    System.out.println(array1);
  }

}

바로 Arrays의 내부 클래스인 ArrayList가 set 방법을 다시 썼기 때문에 상술한 프로그램은 정상적으로 실행될 수 있고 더 이상 지원되지 않는 Operation Exception 이상을 던지지 않습니다.
결과는 다음과 같습니다.
[Welcome, to, Java, world]
[Welcome, to, hello, world] 
장면 사용
상술한 예와 간단한 분석을 보면 Arrays 도구 클래스는 하나의 방법인 asList를 제공합니다. 이 방법을 사용하면 하나의 변장 매개 변수나 그룹을 List로 변환할 수 있습니다.
그러나 생성된 List의 길이는 고정되어 있습니다.수정 작업을 할 수 있다(예를 들어 어떤 위치의 요소를 수정한다).길이에 영향을 주는 동작을 실행할 수 없습니다. (예:add,remove 등)지원되지 않는 OperationException 예외가 발생합니다.
Arrays.AsList는 이미 수조 데이터나 요소가 있는 것에 비교적 적합하지만, 작업을 추가하거나 삭제하지 않고 읽기 작업에만 사용되는 List를 신속하게 구축해야 한다.
만약 이미 알고 있는 수조 데이터에 근거하여 삭제 검사를 할 수 있는 목록 목록을 신속하게 얻으려면 다음과 같은 비교적 간단한 방법이 있다.
자바를 다시 사용합니다.util.Array List를 한 겹으로 포장합니다.

/**
 * @author wangmengjun
 *
 */
public class ArrayExample {

  public static void main(String[] args) {

    /** */
    List<String> array1 = new ArrayList<>(Arrays.asList("Welcome", "to", "Java", "world"));
    System.out.println(array1);

    array1.add("Cool~~~");
    System.out.println(array1);

  }

}

결과는 다음과 같습니다.
[Welcome, to, Java, world]
[Welcome, to, Java, world, Cool~~~]
읽어주셔서 감사합니다. 여러분에게 도움이 되었으면 좋겠습니다. 본 사이트에 대한 지지에 감사드립니다!

좋은 웹페이지 즐겨찾기