Object#cloneを学ぶ(その2) はじめに 書籍Effective Java プログラミング言語ガイドの"項目10 cloneを注意してオーバーライドする"を 読んでみたが、cloneメソッドについて理解できなかったので実装しながらcloneメソッドを理解する。 ■前回のクローンサンプルクラス(TestClone)とクローンサンプル実行クラス(TestCloneRunner) [ java]$ cat TestClone.java public class TestClone implements Cloneable { private int value; public TestClone(int value) { this.value = value; } protected Object clone() throws CloneNotSupportedException { return super.clone(); } public int getValue() { return value; } } [ java]$ javac TestClone.java [ java]$ cat TestCloneRunner.java public class TestCloneRunner { public static void main(String [] args) { TestClone original = new TestClone(1); // 複製を作ってみる try { TestClone cloneObject = (TestClone)original.clone(); System.out.println(cloneObject.getValue()); } catch (CloneNotSupportedException cloneNotEx) { cloneNotEx.printStackTrace(); } } } [ java]$ javac TestCloneRunner.java [ java]$ java TestCloneRunner 1 見事結果で1を出力しました! 再度、Effective Javaを読んでみたところ、"実際には、Cloneableを実装しているクラスは、 適切に機能しているpublicのcloneメソッドを提供することが期待されています。"というセオリーが 書いてありました。気づいてみれば当然ですが、 protectedアクセス修飾子では、外部クラスから呼び出すことが出来ません。同じパッケージか、 TestCloneサブクラスしかcloneメソッドを利用できません。なので、最後にpublicアクセス修飾子で ラップしてcloneメソッドとの戦いを終わりたいと思います。 public class TestClone implements Cloneable { private int value; public TestClone(int value) { this.value = value; } /** * ただアクセス修飾子をpublicにしただけ */ public Object clone() throws CloneNotSupportedException { return super.clone(); } /* protected Object clone() throws CloneNotSupportedException { return super.clone(); } */ public int getValue() { return value; } } ■最後に ・cloneメソッド ・ディープ・コピー ・シャロー・コピー 上記の概念と実装方法が理解できました。cloneメソッドは、コンストラクタを呼び出すことなく インスタンス生成が出来るかなりトリッキーな言語仕様のようです。