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不变
相关文章
相关标签/搜索