Java的拷貝

相似的文章其實已經不少了,我只是記錄下本身的理解ide

  • 淺拷貝:基本類型徹底拷貝值傳遞,引用類型只是引用的傳遞(hashcode一致)
  • 深拷貝:基本類型徹底拷貝值傳遞,引用類型徹底拷貝建立新對象(hashcode不一樣)

經過Object.clone()實現時須要注意如下2點,不然拋出CloneNotSupportedExceptionthis

  • 實現Cloneable接口
  • 重寫clone()方法

淺拷貝(Shallow Copy)

被拷貝對象實現Cloneable接口,而且重寫clone()方法便可code

class Kid {
    private String kname;
    
    public String getKname() {
        return kname;
    }
    
    public void setKname(String kname) {
        this.kname = kname;
    }
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((kname == null) ? 0 : kname.hashCode());
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Kid other = (Kid) obj;
        if (kname == null) {
            if (other.kname != null)
                return false;
        } else if (!kname.equals(other.kname))
            return false;
        return true;
    }
    
}

class BasicObj implements Cloneable {
    private String name;
    private Kid kid;
    
    public BasicObj(String name, Kid kid) {
        super();
        this.name = name;
        this.kid = kid;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Kid getKid() {
        return kid;
    }

    public void setKid(Kid kid) {
        this.kid = kid;
    }

}

public class CopyTest {
    
    public static void main(String[] args) throws CloneNotSupportedException {
        
        Kid k = new Kid();
        k.setKname("Apple");
        
        BasicObj a = new BasicObj("Hello", k);
        BasicObj b = (BasicObj) a.clone();
        
        System.out.println(a == b);
        System.out.println("a.id = " + a.getName() + ", b.id = " + b.getName());
        System.out.println("a.kid.name = " + a.getKid().getKname() + ", b.kid.name = " + b.getKid().getKname());
        System.out.println("a.kid.hashcode = " + a.getKid().hashCode() + ", b.kid.hashcode = " + b.getKid().hashCode());
        
        System.out.println("---------------");
        
        //改變了引用對象的值
        k.setKname("Lemon");
        a.setKid(k);
        //改變本地類型的值
        a.setName("World");

        System.out.println("a.id = " + a.getName() + ", b.id = " + b.getName());
        System.out.println("a.kid.name = " + a.getKid().getKname() + ", b.kid.name = " + b.getKid().getKname());
        System.out.println("a.kid.hashcode = " + a.getKid().hashCode() + ", b.kid.hashcode = " + b.getKid().hashCode());
    }

}

輸出

false
a.id = Hello, b.id = Hello
a.kid.name = Apple, b.kid.name = Apple
a.kid.hashcode = 63476569, b.kid.hashcode = 63476569
---------------
a.id = World, b.id = Hello
a.kid.name = Lemon, b.kid.name = Lemon
a.kid.hashcode = 73304818, b.kid.hashcode = 73304818
  • 改變a的基本類型,b不變
  • 改變a的引用類型,b改變

深拷貝(Deep Copy)

被拷貝對象中的對引用類型須要實現Cloneable接口,且重寫clone()方法(相似遞歸操做,直至拷貝到基本類型爲止)對象

//引用類型對象實現了Cloneable接口
class Kid implements Cloneable {
    private String kname;
    
    public String getKname() {
        return kname;
    }
    
    public void setKname(String kname) {
        this.kname = kname;
    }
    
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((kname == null) ? 0 : kname.hashCode());
        return result;
    }
    
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Kid other = (Kid) obj;
        if (kname == null) {
            if (other.kname != null)
                return false;
        } else if (!kname.equals(other.kname))
            return false;
        return true;
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
    
}

class BasicObj implements Cloneable {
    private String name;
    private Kid kid;
    
    public BasicObj(String name, Kid kid) {
        super();
        this.name = name;
        this.kid = kid;
    }
    
    //改造clone方法,對引用類型對象Kid進行clone操做
    @Override
    protected Object clone() throws CloneNotSupportedException {
        BasicObj bo = new BasicObj(name, kid);
        bo.kid = (Kid) this.kid.clone();
        return bo;
    }
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Kid getKid() {
        return kid;
    }

    public void setKid(Kid kid) {
        this.kid = kid;
    }

}

public class CopyTest {
    
    public static void main(String[] args) throws CloneNotSupportedException {
        
        Kid k = new Kid();
        k.setKname("Apple");
        
        BasicObj a = new BasicObj("Hello", k);
        BasicObj b = (BasicObj) a.clone();
        
        System.out.println(a == b);
        System.out.println("a.id = " + a.getName() + ", b.id = " + b.getName());
        System.out.println("a.kid.name = " + a.getKid().getKname() + ", b.kid.name = " + b.getKid().getKname());
        System.out.println("a.kid.hashcode = " + a.getKid().hashCode() + ", b.kid.hashcode = " + b.getKid().hashCode());
        
        System.out.println("---------------");
        
        //改變了引用對象的值
        k.setKname("Lemon");
        a.setKid(k);
        //改變本地類型的值
        a.setName("World");

        System.out.println("a.id = " + a.getName() + ", b.id = " + b.getName());
        System.out.println("a.kid.name = " + a.getKid().getKname() + ", b.kid.name = " + b.getKid().getKname());
        System.out.println("a.kid.hashcode = " + a.getKid().hashCode() + ", b.kid.hashcode = " + b.getKid().hashCode());
    }

}

輸出

false
a.id = Hello, b.id = Hello
a.kid.name = Apple, b.kid.name = Apple
a.kid.hashcode = 63476569, b.kid.hashcode = 63476569
---------------
a.id = World, b.id = Hello
a.kid.name = Lemon, b.kid.name = Apple
a.kid.hashcode = 73304818, b.kid.hashcode = 63476569
  • 改變a的基本類型,b不變
  • 改變a的引用類型,b不變
相關文章
相關標籤/搜索