オブジェクトを正しく複製する方法は?

Javaでオブジェクトを複製するには、3つの方法があります。

  1. clone()メソッドをオーバーライドし、Cloneable()インターフェイスを実装します。
  2. コピーコンストラクターの使用。
  3. 複製にシリアル化メカニズムを使用する


順番に。 最初の方法は、いわゆる「表面クローン」のメカニズムを使用し、オブジェクトフィールドのクローンを自分で作成することを意味します。 親クラスObjectのclone()



メソッドは保護されているため、宣言をpublicとして再定義する必要があります。 コピーされたプリミティブフィールドとリンクを持つオブジェクトのインスタンスを返します。 そして、元のフィールドとそのクローンリンクフィールドが同じオブジェクトを指していることがわかります。 以下の例は、元のオブジェクトのフィールドとクローンが同時にどのように変化するかを示しています。



 public class CloneTest{ static class Person implements Cloneable{ String name; int age; Car car; Person(Car car,int age,String name) { this.car = car; this.age = age; this.name = name; } @Override public String toString() { return this.name+" {" + "age=" + age + ", car=" + car + '}'; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } static class Car{ public String color; Car(String color) { this.color = color; } @Override public String toString() { return "{" + "color car='" + color + '\'' + '}'; } } public static void main(String[] args) throws CloneNotSupportedException { Car car = new Car("Green"); Person person=new Person(car,25,"Mike"); Person clone = (Person) person.clone(); System.out.println(person); System.out.println(clone); clone.name=new String("Ivan"); clone.car.color="red"; System.out.println(person); System.out.println(clone); } } : Mike {age=25, car={color car='Green'}} Mike {age=25, car={color car='Green'}} Mike {age=25, car={color car='red'}} Ivan {age=25, car={color car='red'}}
      
      





上記の例から、クローンとオリジナルでは、フィールドの1つの状態が同時に変化することがわかります。 次の方法は、コピーコンストラクタを使用することです。



 public class Person { private int age; private String name; public Person(int age, String name){ this.age=age; this.name=name; } //   public Person(Person other) { this(other.getAge(), other.getName()); } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + '}'; } public static void main(String[] args) { Person original = new Person(18, "Grishka"); Person clone = new Person(original); System.out.println(original); System.out.println(clone); } } : Person{age=18, name='Grishka'} Person{age=18, name='Grishka'}
      
      





クラスは、同じクラスのオブジェクトを取り、そのフィールドの値で新しいオブジェクトのフィールドを初期化するコンストラクターを記述します。 クラス開発者は、フィールドの初期化の実装に十分注意する必要があります。



ただし、上記のメソッドは両方とも潜在的なエラーでいっぱいであり、基本的にオブジェクトのコピーを作成します。 クローンを作成する最も便利で柔軟な方法は、シリアル化メカニズムです。 これは、オブジェクトをバイトストリームに格納し、その後そこからオブジェクトを抽出することにあります。 たとえば、猫Vaskaを招待します。彼はいくつかの実験を待っています:



 import java.io.*; class Cat implements Serializable{ private String name; private String color; private int age; public Cat(String name, String color, int age) { this.name = name; this.color = color; this.age = age; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } @Override public String toString() { return "Cat{" + "name='" + name + '\'' + ", color='" + color + '\'' + ", age=" + age + '}'; } } public class BasketCats{ public static void main(String[] args) throws IOException, ClassNotFoundException { Cat vaska = new Cat("Vaska","Gray",4); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream ous = new ObjectOutputStream(baos); //        () ous.writeObject(vaska); ous.close(); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bais); //         Cat cloneVaska = (Cat)ois.readObject(); System.out.println(vaska); System.out.println(cloneVaska); System.out.println("*********************************************"); cloneVaska.setColor("Black"); //       ,         System.out.println(vaska); System.out.println(cloneVaska); } } : Cat{name='Vaska', color='Gray', age=4} Cat{name='Vaska', color='Gray', age=4} ********************************************* Cat{name='Vaska', color='Gray', age=4} Cat{name='Vaska', color='Black', age=4}
      
      





テストの結果として1匹の猫が負傷したわけではありません。Vaskaはストリームに保存され、そこから独立したクローンが復元されたことがわかります。 オブジェクトのクローン作成中にフィールドを処理する特別な必要がない場合、これらの目的にはシリアル化が最も望ましいオプションです。



All Articles