読者です 読者をやめる 読者になる 読者になる

「Java」Object#close でオブジェクトのクローンを作成するサンプル

Object#close を使用することでオブジェクトのクローンが生成できます。

・Object (Java Platform SE 8 )
https://docs.oracle.com/javase/jp/8/docs/api/java/lang/Object.html

ドキュメントに書いてますが Object#close を使用する場合、クローンを生成するオブジェクトのクラスが Cloneable インタフェースを実装している必要があります ( 実装していないと CloneNotSupportedException が発生する )。

・Cloneable (Java Platform SE 8 )
https://docs.oracle.com/javase/jp/8/docs/api/java/lang/Cloneable.html

あと、こちらもドキュメントに書いてますが、Object#close では可変オブジェクトへの参照を保持するフィールドについては浅いコピーになるので注意が必要です。


以下、サンプルになります。

■ CloneTest.java

package test.clone;

import java.util.ArrayList;
import java.util.List;

public class CloneTest implements Cloneable {
  private int i;
  private String s;
  private List<String> l;
  
  public CloneTest(int i, String s, List<String> l) {
    this.i = i;
    this.s = s;
    this.l = l;
  }
  
  public void setI(int i) { this.i = i; }
  public void setS(String s) { this.s = s; }
  public void setL(List<String> l) { this.l = l; }
  
  public int getI() { return i; }
  public String getS() { return s; }
  public List<String> getL() { return l; }
  
  public String toString() {
    return "[i:" + i +"] [s:" + s + "] [l:" + l.toString() +"]";
  }
  
  public static void main(String[] args) {
    List<String> l = new ArrayList<>();
    l.add("aaa");
    CloneTest inst = new CloneTest(100, "hoge", l);
    
    CloneTest clone = null;
    try {
      clone = (CloneTest)inst.clone();
    } catch (CloneNotSupportedException e) { e.printStackTrace(); }
    
    System.out.println(inst);
    System.out.println(clone);
    
    // inst のフォールドを変更してみる
    String s = inst.getS();
    s = "uga";
    inst.setS(s);
    List<String> ll = inst.getL();
    l.add("bbb");
    inst.setL(l);
    System.out.println(inst);
    System.out.println(clone);
  }
}

■ 実行結果

[i:100] [s:hoge] [l:[aaa]]
[i:100] [s:hoge] [l:[aaa]]
[i:100] [s:uga] [l:[aaa, bbb]]
[i:100] [s:hoge] [l:[aaa, bbb]]

inst のフィールド l の変更が clone 側にも影響している様子が確認できます。

可変オブジェクトのフィールドを深いコピーにしたいという場合は、以下のような感じで Object#clone をオーバーライドしてやる必要があります。

  public Object clone() throws CloneNotSupportedException {
    super.clone();
    List<String> copy = new ArrayList<>(l);
    return new CloneTest(i, s, copy);
  }

Object#clone をオーバーライドした際のサンプルの実行結果は以下の通りです。

[i:100] [s:hoge] [l:[aaa]]
[i:100] [s:hoge] [l:[aaa]]
[i:100] [s:uga] [l:[aaa, bbb]]
[i:100] [s:hoge] [l:[aaa]]

inst のフィールド l の変更が clone 側には影響していないことが確認できます。


簡単になりますが、以上です。

[ 環境情報 ]
Windows 7 SP1
Java SE 8 Update 74