ホームページ  >  記事  >  Java  >  Java Cloneable インターフェイスのディープ コピーおよびシャロー コピー メソッド

Java Cloneable インターフェイスのディープ コピーおよびシャロー コピー メソッド

PHPz
PHPz転載
2023-04-28 08:49:131186ブラウズ

    クローン可能なインターフェイスのソース コード

    クローン可能なインターフェイス:

    このインターフェイスを実装するクラスは次のとおりです。 java.lang.Object の clone() メソッドは、クラス インスタンス、つまりプロパティ間のコピーを実装するために、合法的に呼び出すことができると推測されます。

    クラスが Cloneable インターフェイスを実装していない場合、 clone() メソッドが呼び出されるときに、CloneNotSupportedException 例外がスローされます。

    一般に、Cloneable インターフェースを実装する サブクラスは、パブリック アクセス許可を持つ clone() メソッド をオーバーライドする必要があります (ただし、java.Object クラスの clone メソッドは保護された型です)

    Cloneable インターフェイスには clone() メソッドが含まれていないことに注意してください。したがって、Cloneable インターフェイスを実装しただけでは、オブジェクトを正常に複製することはできません。

    [理由:リフレクティブに呼び出したとしても、クローン作成メソッドが成功する保証はありません] - 私の個人的な理解は次のとおりです。 Clone() メソッドをオーバーライドするかどうか、または「浅いコピーとコピー」の存在が原因です。ディープコピー」の問題。

    class Pet implements Cloneable{
        //properties
        private String name;
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public Pet() {
        }
        public Pet(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Pet{" +
                    "name='" + name + '\'' +
                    '}';
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pet pet = (Pet) o;
            return Objects.equals(name, pet.name);
        }
        @Override
        public int hashCode() {
            return Objects.hash(name);
        }
    //    @Override
    //    public Pet clone() {
    //        try {
    //            return (Pet)super.clone();
    //        } catch (CloneNotSupportedException e) {
    //            e.printStackTrace();
    //        }
    //        return null;
    //    }
    }

    浅いコピーの場合

    Pet クラス定義

    注: Pet クラスは Cloneable インターフェイスを実装しますが、Clone() メソッドをオーバーライドしません (明らかに:この Pet クラスにはオブジェクトのクローンを作成する機能がありません)。

    class Pet implements Cloneable{
        //properties
        private String name;
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public Pet() {
        }
        public Pet(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Pet{" +
                    "name='" + name + '\'' +
                    '}';
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pet pet = (Pet) o;
            return Objects.equals(name, pet.name);
        }
        @Override
        public int hashCode() {
            return Objects.hash(name);
        }
    //    @Override
    //    public Pet clone() {
    //        try {
    //            return (Pet)super.clone();
    //        } catch (CloneNotSupportedException e) {
    //            e.printStackTrace();
    //        }
    //        return null;
    //    }
    }

    パーソン クラス定義

    注: パーソン クラスは Cloneable インターフェイスを実装し、Clone() メソッドもオーバーライドします。では、 Person クラスにはオブジェクトのクローンを作成する機能があるのでしょうか? (浅いコピーの問題により、このオブジェクトのクローン作成機能は不完全で欠陥があると考えられます)。

    class Pet implements Cloneable{
        //properties
        private String name;
        public void setName(String name) {
            this.name = name;
        }
        public String getName() {
            return name;
        }
        public Pet() {
        }
        public Pet(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Pet{" +
                    "name='" + name + '\'' +
                    '}';
        }
        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pet pet = (Pet) o;
            return Objects.equals(name, pet.name);
        }
        @Override
        public int hashCode() {
            return Objects.hash(name);
        }
    //    @Override
    //    public Pet clone() {
    //        try {
    //            return (Pet)super.clone();
    //        } catch (CloneNotSupportedException e) {
    //            e.printStackTrace();
    //        }
    //        return null;
    //    }
    }

    シャロー コピーの問題コード テスト

    現時点で、Person クラスのオブジェクト クローン作成機能が不完全で欠陥があると言われているのはなぜですか?現時点では、 Person オブジェクトを通じて clone() メソッドが呼び出され、オブジェクトが複製されると、そのメンバー属性 pet (Pet クラスのオブジェクト) の値の複製は、メモリ アドレスの単純なコピーにすぎないためです。ヒープ領域にあります。

    つまり: 率直に言うと、Person オブジェクトの pet 属性値と複製されたオブジェクトは同じヒープ領域メモリを共有します。問題は明らかです。複製されたオブジェクトの pet 属性が設定されると、元の person オブジェクトの pet 属性値に明らかに影響します。

    コードのデモは次のとおりです:

      //methods
        public static void main(String[] args) throws CloneNotSupportedException {
            testPerson();
        }
        public static void testPerson() throws CloneNotSupportedException {
            Person p=new Person("张三",14,new Pet("小黑"));
            System.out.println(p);
            Person clone = (Person)p.clone();
            System.out.println(clone);
            System.out.println(p.equals(clone));
            System.out.println(p.getPet()==clone.getPet());
            System.out.println("************");
            clone.setAge(15);
            System.out.println(p);
            System.out.println(clone);
            System.out.println(p.equals(clone));
            System.out.println("************");
            clone.getPet().setName("小黄");
            System.out.println(p);
            System.out.println(clone);
            System.out.println(p.equals(clone));
            System.out.println(p.getPet()==clone.getPet());
        }

    Java Cloneable インターフェイスのディープ コピーおよびシャロー コピー メソッド

    ディープ コピーのケース

    それでは、ディープ コピーの実装方法を説明します。コピー?鍵は、上記の場合のコードのコメント行にあります。

    Pet クラスは clone() メソッドをオーバーライドします

    Java Cloneable インターフェイスのディープ コピーおよびシャロー コピー メソッド

    Pet の clone メソッドを Person の clone() メソッドで呼び出します

    Java Cloneable インターフェイスのディープ コピーおよびシャロー コピー メソッド

    浅いコピーの問題解決 - 深いコピー コードのテスト

    テスト コードは変更されていないため、再度実行します:

    Java Cloneable インターフェイスのディープ コピーおよびシャロー コピー メソッド

    以上がJava Cloneable インターフェイスのディープ コピーおよびシャロー コピー メソッドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。