Javaのcloneメソッド--深いコピーと浅いコピー


Cloneableインタフェースはタグインタフェースであり、以下のように定義されています.
ここでこのインタフェースの使い方を分析すると、cloneメソッドはObject種で定義され、protected型であり、このインタフェースを実現してこそ、クラスのインスタンスでcloneメソッドを呼び出すことができ、そうでなければCloneNotSupportExceptionが投げ出される.Objectにおけるデフォルトのインプリメンテーションは浅いコピー,すなわち表面コピーであり,深層コピーを実現する必要がある場合はクラス内の可変ドメインに対して新しい実を生成しなければならない.
Objectはオブジェクトコピーのデフォルトメソッドcloneメソッドを提供していますが、このメソッドには欠陥があり、オブジェクトのすべての属性をすべてコピーするのではなく、選択的なコピーを提供しています.コピールールは次のとおりです.
1、基本タイプ
変数が基本タイプの場合、int、float、longなどの値をコピーします.
2、String文字列
これは特殊で、アドレスをコピーして参照していますが、変更すると文字列プール(String Pool)から新しい文字列が再生成され、元の文字列オブジェクトは変わらず、ここではStringが基本タイプであると考えられます.
3、対象
変数がインスタンス・オブジェクトである場合、コピー・アドレスは参照されます.つまり、新しくコピーされたオブジェクトは、アクセス権の制限を受けずに既存のオブジェクトと共有されます.これはJavaでクレイジーです.アクセス権限の定義を突破し、private修飾変数が2つのインスタンスオブジェクトにアクセスできるためです.
public class Client {
    public static void main(String[] args){
        //    
        Person p = new Person("  ");
        //     
        Person son1 = new Person("   ",p);
        //     
        Person son2 = son1.clone();
        //   son2  
        son2.setName("   ");
          
        //    ,    
        son2.getFather().setName("  ");
          
        System.out.println(son1.getName()+"      "+son1.getFather().getName());
        System.out.println(son2.getName()+"      "+son2.getFather().getName());
    }
}
class Person implements Cloneable{
      
    private String name;
      
    private Person father;
      
    public Person(String name){
        this.name=name;
    }
      
    public Person(String name,Person father){
        this.name=name;
        this.father=father;
    }
      
    //     
    @Override
    public Person clone(){
        Person p = null;
        try{
            //  Object    
            p = (Person) super.clone();
              
            /**
             * 1.             ,     
             * 2.               ,                    ,
             *           ,         
             */
            p.setFather(new Person(p.getFather().getName()));
        }catch(CloneNotSupportedException e){
            e.printStackTrace();
        }
        return p;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Person getFather() {
        return father;
    }
    public void setFather(Person father) {
        this.father = father;
    }
}