目次
「ディープコピー」と「シャローコピー」の違い
シャローコピーとは
シャローコピーとは浅い(shallow)コピーと呼ばれ、実体(データ)のコピーを行わないで、オブジェクトをコピーする方式です。要するに見せかけの複製を作るコピーです。
オブジェクトはメモリ上にある実体(データ)を参照します。シャローコピーでは、実体(データ)のコピーを行わないので、シャローコピーで生成されたオブジェクトは、コピー元オブジェクトと同じ実体(データ)を参照することとなります。
シャローコピーで作られたオブジェクトは、参照している実体(データ)が同じです。ということは、どちらかのオブジェクトを変更したら、もう片方のオブジェクトも変更されます。なぜなら同じ実体(データ)を参照しているからです。
スポンサーリンク
ディープコピーとは
ディープコピーとは深い(deep)コピーと呼ばれ、実体(データ)も含めてオブジェクトをコピーする方式です。要するに完全な複製を作るコピーです。
オブジェクトはメモリ上にある実体(データ)を参照します。ディープコピーでは、オブジェクトと参照する実体(データ)をコピーします。そのため、コピー元とコピー先は別々の実体(データ)を参照することとなります。
ディープコピーで作られたオブジェクトは、別々の実体(データ)を参照します。そのため、どちらかのオブジェクトを変更しても、もう片方のオブジェクトには影響を与えません。
「ディープコピー」と「シャローコピー」のコピー例
シャローコピーのコピー例
コピー対象のオブジェクト(データを格納する箱)は以下とします。
package entity;
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
シャローコピーのコピー例
package main;
import entity.User;
public class Start {
public static void main(String[] args) {
User user1 = new User();
// user1の名前を設定
user1.setName("変更前の名前");
// シャローコピー
User user2 = user1;
// user2の名前を変更
user2.setName("変更後の名前");
System.out.println("user1の名前:" + user1.getName());
System.out.println("user2の名前:" + user2.getName());
}
}
スポンサーリンク
実行結果は以下のように「コピー元の名前」「コピー先の名前」には「変更後の名前」が設定されています。
これはどちらもメモリ上にある同じ実体(データ)を参照していることが理由です。
コピー元の名前:変更後の名前
コピー先の名前:変更後の名前
ディープコピーのコピー例
コピー対象のオブジェクト(データを格納する箱)は以下とします。Javaが提供しているclone(複製)を作るインタフェースである「Cloneable」をimplements しています。
package entity;
public class User2 implements Cloneable {
private String name;
@Override
public User2 clone() {
User2 user2 = null;
try {
user2 = (User2) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return user2;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ディープコピーのコピー例
package main;
import entity.User2;
public class Start2 {
public static void main(String[] args) {
User2 user2 = new User2();
// user1の名前を設定
user2.setName("変更前の名前");
// ディープコピー
User2 copyUser2 = user2.clone();
// user2の名前を変更
copyUser2.setName("変更後の名前");
System.out.println("コピー元の名前:" + user2.getName());
System.out.println("コピー先の名前:" + copyUser2.getName());
}
}
実行結果は以下のように「コピー元の名前」「コピー先の名前」には別々の名前が設定されています。
これはシャローコピーとは違い、メモリ上にある別の実体(データ)を参照していることが理由です。
コピー元の名前:変更前の名前
コピー先の名前:変更後の名前