・(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]