Javaのcloneメソッドって?

Objectとcloneメソッド

この前本屋さんでJavaの本を読んでいたら,驚くべきことが書いてあった.
cloneメソッドでコピーを代入するのと,単に=で代入するのでは処理が異なるらしい.

JavaのObject

Javaを少しやったことがある人なら,JavaのすべてのクラスはObjectクラスの子クラスであるということは理解していると思います.
自分で何も継承していないクラスを定義しようとも,それは自動的にObjectクラスを継承しています.

cloneメソッド

Objectクラスにはcloneメソッドが定義されています.その他にも,toStringやhashCodeなどいろいろあります.
詳しくはここを見よう
Object (Java Platform SE 8)
cloneメソッドとはそのオブジェクトをコピーを返すメソッドです.
   

試してみた

現在の時間と10日前の時間を取得するコードを書いてみる.

cloneメソッドを使う場合

書いたコード
//現在の時間を表すCalendarオブジェクトを宣言
Calendar a=Calendar.getInstance();
//cloneメソッドで返ってきたオブジェクトを代入
Calendar b=(Calendar)a.clone(); 

System.out.println(a.get(Calendar.MONTH)+"/"+a.get(Calendar.DATE));
System.out.println(b.get(Calendar.MONTH)+"/"+b.get(Calendar.DATE));

//bだけ10日前にする
b.add(Calendar.DATE, -10);

System.out.println(a.get(Calendar.MONTH)+"/"+a.get(Calendar.DATE));
System.out.println(b.get(Calendar.MONTH)+"/"+b.get(Calendar.DATE));
結果
10/12
10/12
10/12
10/2

予定通りbだけが10日前になっている.

cloneメソッドを使わない場合

書いたコード
//現在の時間を表すCalendarオブジェクトを宣言
Calendar a=Calendar.getInstance();
//aをそのままbに代入
Calendar b=a; 

System.out.println(a.get(Calendar.MONTH)+"/"+a.get(Calendar.DATE));
System.out.println(b.get(Calendar.MONTH)+"/"+b.get(Calendar.DATE));

//bだけ10日前にする
b.add(Calendar.DATE, -10);

System.out.println(a.get(Calendar.MONTH)+"/"+a.get(Calendar.DATE));
System.out.println(b.get(Calendar.MONTH)+"/"+b.get(Calendar.DATE));
結果
10/12
10/12
10/2
10/2

あっれれ〜,おかしいぞ〜変更してないはずのaまで10日前になってるよ.

まとめ

cloneはそのオブジェクトのコピー(アドレスは異なる)を作ってくれるメソッドで,
Objectクラスに定義されてるからどんなクラスでも標準装備.
オブジェクトを単に=で代入すると,それは全く同じもの(アドレスが同じ)が代入される.
知らないで適当にやってるとバグを生みかねないから気をつけよう!!
こんなこと誰でも知ってる気がする…