



スポンサーリンク
目次
ディープコピーの実装方法
[方法1] Cloneableを使ってディープコピー(clone)する
Javaで提供されているCloneableインタフェースを実装することで、ディープコピーすることができます。
1. Cloneableをimplementsし、cloneメソッドを実装する
Cloneableを使ってディープコピーを実装する場合は、コピー対象となるオブジェクトがCloneableをimplementsする必要があります。
そしてcloneメソッドをOverrideしclone処理を書きます。
具体的なサンプルは以下の通りです。
cloneメソッド内では、Schoolクラスのcloneの作成、そしてリストで保持しているStudentクラスのcloneを作成しています。
package entity; import java.util.ArrayList; import java.util.List; /** * 学校クラス */ public class School implements Cloneable { /** * 学校名 */ private String schoolName; /** * 生徒リスト */ private List<Student> studentList; /** * ディープコピー */ @Override public School clone() { School school = null; try { school = (School) super.clone(); // 生徒リストをコピー school.studentList = new ArrayList<Student>(); if (this.studentList != null) { for (Student sudent : this.studentList) { school.studentList.add(sudent.clone()); } } }catch (Exception e){ school = null; } return school; } public String getSchoolName() { return schoolName; } public void setSchoolName(String schoolName) { this.schoolName = schoolName; } public List<Student> getStudentList() { return studentList; } public void setStudentList(List<Student> studentList) { this.studentList = studentList; } }
package entity; /** * 生徒クラス */ public class Student implements Cloneable { /** * 名前 */ private String name; /** * ディープコピー */ @Override public Student clone() { Student student = null; try { student = (Student) super.clone(); }catch (Exception e){ student = null; } return student; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
2. cloneでディープコピーする
Cloneableをimplementsしているオブジェクトさえ作れれば、後はclone()を呼び出すことでディープコピーすることができます。
School school = new School(); // ディープーコピー School copySchool = school.clone();
スポンサーリンク
[方法2] SerializationUtilsライブラリで、ディープコピー(clone)する
apache.commons.lang.SerializationUtilsクラスが提供しているcloneメソッドでディープコピーすることができます。
SerializationUtilsクラスは、Apache Commons Lang(commons-lang×.jar ※×はバージョン)のライブラリを使うことで利用可能です。
1. Serializableをimplementsする
SerializationUtilsクラスで「ディープコピー」するためには、コピー対象のオブジェクトがSerializableをimplementsしていなければコピーできません。
そのため、コピー対象のオブジェクトはSerializableをimplementsします。
具体的なサンプルは以下の通りです。
package entity; import java.io.Serializable; import java.util.List; /** * 学校クラス */ public class School2 implements Serializable { /** * 学校名 */ private String schoolName; /** * 生徒リスト */ private List<Student2> studentList; public String getSchoolName() { return schoolName; } public void setSchoolName(String schoolName) { this.schoolName = schoolName; } public List<Student2> getStudentList() { return studentList; } public void setStudentList(List<Student2> studentList) { this.studentList = studentList; } }
package entity; import java.io.Serializable; /** * 生徒クラス */ public class Student2 implements Serializable { /** * 名前 */ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
2. cloneでディープコピーする
コピー対象のオブジェクトがSerializableをimplementsしていれば、後はclone()を呼び出すことでディープコピーすることができます。
School2 school = new School2(); // ディープーコピー School2 copySchool = SerializationUtils.clone(school);
スポンサーリンク
[方法3] コンストラクタ等で詰め替える
コンストラクタ等を利用して各項目を詰め替えることで「ディープコピー」することができます。項目が多いと大変 または メンテナンス性が悪いなどのデメリットはありますが、シンプルな方法です。
1. コンストラクタで詰め替える処理を実装する
コンストラクタで詰め替える処理を実装します。
具体的なサンプルは以下の通りです。
package entity; import java.util.ArrayList; import java.util.List; /** * 学校クラス */ public class School3 { /** * コンストラクタ */ public School3() {} /** * コピー用コンストラクタ * @param schoolName 学校名 * @param studentList 生徒リスト */ public School3(School3 school) { this.schoolName = school.getSchoolName(); if (school.getStudentList() != null) { this.studentList = new ArrayList<Student3>(); for(Student3 student : school.getStudentList()) { this.studentList.add(new Student3(student)); } } } /** * 学校名 */ private String schoolName; /** * 生徒リスト */ private List<Student3> studentList; public String getSchoolName() { return schoolName; } public void setSchoolName(String schoolName) { this.schoolName = schoolName; } public List<Student3> getStudentList() { return studentList; } public void setStudentList(List<Student3> studentList) { this.studentList = studentList; } }
package entity; /** * 生徒クラス */ public class Student3 { /** * コンストラクタ */ public Student3() {} /** * コピー用コンストラクタ * @param name 名前 */ public Student3(Student3 student) { this.name = student.getName(); } /** * 名前 */ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
2. インスタンス生成時にディープコピーする
コピー用のコンストラクタを用意したら、後はインスタンス生成時に引数としてコピー元オブジェクトを渡すだけで「ディープコピー」することができます。
School3 school = new School3(); // ディープーコピー School3 copySchool = new School3(school);
スポンサーリンク
[方法4] ディープコピーの処理を自作する
最後は「ディープコピー」の処理を自作する方法です。
1. ディープコピー用の関数を作る
ディープコピー用の関数を作成します。
具体的なサンプルは以下の通りです。
※以下の関数では、コピー対象のオブジェクトはSerializableをimplementsしている必要があります。
/** * ディープコピー * @param obj コピー元オブジェクト * @return コピー先オブジェクト * @throws IOException * @throws ClassNotFoundException */ public static Object deepcopy(Object obj) throws IOException, ClassNotFoundException { Object copy = null; try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos);) { // 符号化されたオブジェクトのデータを保持する配列を取得 oos.writeObject(obj); byte[] buff = baos.toByteArray(); // バイト配列から、オブジェクトを複合化 try (ByteArrayInputStream bais = new ByteArrayInputStream(buff); ObjectInputStream os = new ObjectInputStream(bais);) { copy = os.readObject(); } } return copy; }
2. 関数を呼び出しディープコピーする
自作で作成した関数を呼び出し「ディープコピー」を行います。
School2 school = new School2(); // ディープーコピー School2 copySchool = (School2) deepcopy(school);