ksino's diary

覚えたことを忘れないように、小さなことでも書いていく。

Javaでオブジェクトのディープクローンを行う

ディープクローンという言葉があるかどうか分かりませんが。。
オブジェクトのディープコピーを返すメソッドを作成します。
方法はいくつかあるかと思いますが、ここではSerializableインタフェースを用いてやってみます。

    public static Object deepClone(Serializable s) {
        if (s == null) {
            return null;
        }
        byte[] bytes = null;
        try (
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                ) {
            oos.writeObject(s);
            bytes = baos.toByteArray();
        } catch (IOException ex) {
            // TODO 例外処理
        }
        Object ret = null;
        if (bytes != null) {
            try (
                    ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
                    ObjectInputStream ois = new ObjectInputStream(bais);
                    ) {
                ret = ois.readObject();
            } catch (IOException | ClassNotFoundException ex) {
                // TODO 例外処理
            }
        }
        return ret;
    }

テストコードは以下の通りです。

    @Test
    public void testDeepClone() {
        
        // テストデータの準備
        int a = 1;
        String b = "あいうえお";
        int c_a = 2;
        String c_b = "かきくけこ";
        
        TestDto o1 = new TestDto();
        o1.setA(a);
        o1.setB(b);
        ChildDto child = new ChildDto();
        child.setC_a(c_a);
        child.setC_b(c_b);
        o1.setChild(child);
        
        // 対象メソッドの実行
        Object o2 = DeepCloneUtil.deepClone(o1);
        
        // テスト結果の検証
        assertNotNull(o2);
        assertNotSame(o1, o2);
        assertTrue(o2 instanceof TestDto);
        assertEquals(a, ((TestDto)o2).getA());
        assertEquals(b, ((TestDto)o2).getB());
        
        assertNotNull(((TestDto)o2).getChild());
        assertNotSame(child, ((TestDto)o2).getChild());
        assertEquals(c_a, ((TestDto)o2).getChild().getC_a());
        assertEquals(c_b, ((TestDto)o2).getChild().getC_b());
    }
public class TestDto implements Serializable {
    private int a;
    private String b;
    private ChildDto child;

    public ChildDto getChild() {
        return child;
    }

    public void setChild(ChildDto child) {
        this.child = child;
    }

    public int getA() {
        return a;
    }

    public void setA(int a) {
        this.a = a;
    }

    public String getB() {
        return b;
    }

    public void setB(String b) {
        this.b = b;
    }
}
public class ChildDto implements Serializable {
    private int c_a;
    private String c_b;

    public int getC_a() {
        return c_a;
    }

    public void setC_a(int c_a) {
        this.c_a = c_a;
    }

    public String getC_b() {
        return c_b;
    }

    public void setC_b(String c_b) {
        this.c_b = c_b;
    }
}