今更ながら躓いたので動作チェックのメモ。
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
・・・
オブジェクト同士が同じオブジェクトか判断するとき
hashCode()がオーバーライドされていて使えないときは
System.identityHashCode()を使うといい.
@Test
public final void objectCheck() {
List original = new ArrayList();
List original2 = original;
List copyConst = new ArrayList(original);
System.out.println("original = " + System.identityHashCode(original));
System.out.println("original2 = " + System.identityHashCode(original2));
System.out.println("copyConst = " + System.identityHashCode(copyConst));
}
Objectクラスのclone()はあくまでもshallowコピーなので
メンバが参照型でインスタンスが入っている場合clone()を使うと共有してしまう.
@Test
public final void shallowCopyTest() {
CopySareru shallow1 = new CopySareru();
CopySareru shallow2 = shallow1.clone();
System.out.println("shallow1.getMemberAddress() = " + shallow1.getMemberAddress());
System.out.println("shallow2.getMemberAddress() = " + shallow2.getMemberAddress());
}
shallowコピーとはいえコピー対象同士のオブジェクトは別物なので
clone()後にメンバをインスタンス化すればメンバを共有することはない.
@Test
public final void copyAndInitTest() {
CopySareru deep1 = new CopySareru();
CopySareru deep2 = deep1.clone();
deep1.init();
deep2.init();
System.out.println("deep1.getMemberAddress() = " + deep1.getMemberAddress());
System.out.println("deep2.getMemberAddress() = " + deep2.getMemberAddress());
}
class CopySareru implements Cloneable {
private List member;
public CopySareru() {
member = new ArrayList();
}
public void init() {
member = new ArrayList();
}
public int getMemberAddress() {
return System.identityHashCode(member);
}
public CopySareru clone() {
CopySareru cs = null;
try {
cs = (CopySareru) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return cs;
}
}
結果
Tests run: 1, Failures: 0, Errors: 0, Skipped: 1, Time elapsed: 0.021 sec
original = 1689843956
original2 = 1689843956
copyConst = 977993101
shallow1.getMemberAddress() = 5592464
shallow2.getMemberAddress() = 5592464
deep1.getMemberAddress() = 1830712962
deep2.getMemberAddress() = 1112280004
参考: Javaクローンメモ(Hishidama's Java Cloneable Memo)