LoginSignup
1
2

More than 3 years have passed since last update.

Java Listをcloneする.

Last updated at Posted at 2019-08-15

・(SetやMapでも同じですが)ArrayListはCloneableですが、ListはCloneableではありません。

・ArrayListではなくListで渡されたものをcloneしたいが、素直にはできないという状況があります。どうすればよいか?

・下記にサンプルを示しますが、実際のオブジェクトのクラスのcloneメソッドを取得してinvokeするという方法があります。

・このあたりは、Javaを使っていて悔しい思いをするところです。int⇔Integerは代入できるのにint[]⇔Integer[]は代入できないとかいうのも同じような悔しさです。

・蛇足ながら、例えばHashSetでkeySetをすると、HashMap$KeySetが戻りますが、これはCloneableではなく、サンプルで示した方法ではcloneできません。こういうの、困るよね....。

・もう一つ蛇足。サンプルでgetDeclaredMethodを使っています。
 ・getDeclaredMethod(getDeclaredMethods)は当該のクラスで宣言されたメソッドを取得します。
 ・getMethod(getMethods)は、基底クラスで宣言されたメソッドも含めて取得します。

★追記★
下記のfelisさんの指摘にあるように、Java10からはListのcopyOfというものが使えます。
下記のテストプログラムは、JDK1.6で実行しています。

package jp.avaj.lib.algo;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import jp.avaj.lib.test.ArTest;
import jp.avaj.lib.test.L;

/**
  Listをcloneする

  ArrayListはcloneableだが、Listはcloneableではない.SetやMapなどでも同じ.
 */
public class Tips0056 {
  public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    List<String> list = ArList.construct("a,b,c");
    List<String> newList;

    // これはコンパイルエラー
    //newList = (List<String>)list.clone();
    L.p("これならできる"); // しかしListで渡された時はArrayListであるかどうかは不明.
    newList = (List<String>)((ArrayList)list).clone();
    L.p(newList.toString());

    L.p("実際のクラスからcloneメソッドを取得してinvokeする");
    // 実際のクラスでcloneメソッドを取得する.パラメータがある時は後ろに指定するが今は不要
    Method cloneMethod = list.getClass().getDeclaredMethod("clone");
    // メソッドがない時は例外が発生するので、ここに来ればメソッドはある.

    // メソッドを実行する.パラメータがある時は後ろに指定するが今は不要.
    newList = (List<String>)cloneMethod.invoke(list);

    // 結果を確認する.
    ArTest.equals("clone","expected",3,"size",newList.size());
    ArTest.equals("clone","expected","a","(0)",newList.get(0));
    ArTest.equals("clone","expected","b","(1)",newList.get(1));
    ArTest.equals("clone","expected","c","(2)",newList.get(2));
    // 目で見て確認する
    L.p(newList.toString());
  }
}

結果は次のとおり

これならできる
[a, b, c]
実際のクラスからcloneメソッドを取得してinvokeする
OK clone:expected=3:size=3
OK clone:expected=a:(0)=a
OK clone:expected=b:(1)=b
OK clone:expected=c:(2)=c
[a, b, c]

1
2
3

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
1
2