LoginSignup
8
7

More than 3 years have passed since last update.

【Java】配列をArrayListに変換する ※注意あり

Last updated at Posted at 2020-04-29

配列をArrayListに変換する方法と注意点・落とし穴

配列をArrayListに変換する方法を紹介します。
絶対にハマる落とし穴があるので、最後まで読んでください!

ListToArray.java
String[] array ={"A","B","C"};
List<String> list =  Arrays.asList(array);
System.out.println("配列 = " + Arrays.toString(array));
System.out.println("List = " + list.toString());

結果

配列 = [A, B, C]
List = [A, B, C]

できた!簡単じゃん。

・・・でも

要素を追加してみる

ListToArray.java
//中略
List<String> list =  Arrays.asList(array);
list.add("D"); //Dを追加!

結果

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at java.util.AbstractList.add(AbstractList.java:108)
    at codeSample.ListToArray.main(ListToArray.java:13)

エラーになる

なぜか

返すクラスを取得してみる

ListToArray.java
//中略
List<String> list =  Arrays.asList(array);
ArrayList<String> arrayList = new ArrayList<String>();
System.out.println("通常のArrayList = " + arrayList.getClass());
System.out.println("配列からの変換 = " + list.getClass());

結果

通常のArrayList = class java.util.ArrayList
配列からの変換 = class java.util.Arrays$ArrayList

ん、なんか違う!

深堀してみる

java.util.Arrays.class
//中略
public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a; // ←←←finalになってる!

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);    // 参照コピー(追記)
        }

        @Override
        public int size() {
            return a.length;
        }
//中略
    }

Arraysクラスの内部クラスに定義された簡易版のArrayListを返していた!
※E[] aには元の配列が参照コピーされる。 (追記
addメソッドの定義がなく、AbstractList.add(E e)にいくため、UnsupportedOperationExceptionが発生していた。

java.util.AbstractList.class
public boolean add(E e) {
    add(size(), e);
    return true;
}
//中略
public void add(int index, E element) {
    throw new UnsupportedOperationException();
}

修正

ListToArray.java
//中略
ArrayList<String> arrayList = new ArrayList<String>(Arrays.asList(array));
arrayList.add("D");
System.out.println("配列 = " + Arrays.toString(array));
System.out.println("List = " + arrayList.toString());

新しくArrayListの領域をnewして変換する。 (追記

結果

配列 = [A, B, C]
List = [A, B, C, D]

Arrays.asList()は型変換するだけで、参照先メモリ領域もそのままということですね。 (追記

8
7
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7