Cloneable和clone的使用,深入理解深度克隆与浅度克隆(一)

399 篇文章 12 订阅

一.Cloneable 的用途

Cloneable和Serializable一样都是标记型接口,它们内部都没有方法和属性,implements Cloneable表示该对象能被克隆,能使用Object.clone()方法。如果没有implements Cloneable的类调用Object.clone()方法就会抛出CloneNotSupportedException。

二.克隆的分类

  1.  浅克隆(shallow clone),浅拷贝是指拷贝对象时仅仅拷贝对象本身和对象中的基本变量,而不拷贝对象包含的引用指向的对象。
  2.   深克隆(deep clone),深拷贝不仅拷贝对象本身,而且拷贝对象包含的引用指向的所有对象。

举例区别一下:对象A1中包含对B1的引用,B1中包含对C1的引用。浅拷贝A1得到A2,A2中依然包含对B1的引用,B1中依然包含对C1的引用。深拷贝则是对浅拷贝的递归,深拷贝A1得到A2,A2中包含对B2(B1的copy)的引用,B2中包含对C2(C1的copy)的引用。

三.克隆的举例

要让一个对象进行克隆,其实就是两个步骤:

  1.   让该类实现java.lang.Cloneable接口;
  2.   重写(override)Object类的clone()方法。
public class Wife implements Cloneable {
    private int id;
    private String name;
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public Wife(int id,String name) {
        this.id = id;
        this.name = name;
    }
 
    @Override
    public int hashCode() {//myeclipse自动生成的
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
 
    @Override
    public boolean equals(Object obj) {//myeclipse自动生成的
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Wife other = (Wife) obj;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
 
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
 
    /**
     * @param args
     * @throws CloneNotSupportedException 
     */
    public static void main(String[] args) throws CloneNotSupportedException {
        Wife wife = new Wife(1,"wang");
        Wife wife2 = null;
        wife2 = (Wife) wife.clone();
        System.out.println("class same="+(wife.getClass()==wife2.getClass()));//true
        System.out.println("object same="+(wife==wife2));//false
        System.out.println("object equals="+(wife.equals(wife2)));//true
    }
}

四.浅克隆的举例

public class Husband implements Cloneable {
    private int id;
    private Wife wife;
    
    public Wife getWife() {
        return wife;
    }
 
    public void setWife(Wife wife) {
        this.wife = wife;
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public Husband(int id) {
        this.id = id;
    }
 
    @Override
    public int hashCode() {//myeclipse自动生成的
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        return result;
    }
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
 
    @Override
    public boolean equals(Object obj) {//myeclipse自动生成的
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Husband other = (Husband) obj;
        if (id != other.id)
            return false;
        return true;
    }
 
    /**
     * @param args
     * @throws CloneNotSupportedException 
     */
    public static void main(String[] args) throws CloneNotSupportedException {
        Wife wife = new Wife(1,"jin");
        Husband husband = new Husband(1);
        Husband husband2 = null;
        husband.setWife(wife);
        husband2 = (Husband) husband.clone();
        System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true
        System.out.println("husband object same="+(husband==husband2));//false
        System.out.println("husband object equals="+(husband2.equals(husband)));//true
        System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true
        System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//true
        System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true
    }
}

五.深克隆的举例

如果要深克隆,需要重写(override)Object类的clone()方法,并且在方法内部调用持有对象的clone()方法;注意如下代码的clone()方法
 

public class Husband implements Cloneable {
    private int id;
    private Wife wife;
    
    public Wife getWife() {
        return wife;
    }
 
    public void setWife(Wife wife) {
        this.wife = wife;
    }
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public Husband(int id) {
        this.id = id;
    }
 
    @Override
    public int hashCode() {//myeclipse自动生成的
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        return result;
    }
 
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Husband husband = (Husband) super.clone();
        husband.wife = (Wife) husband.getWife().clone();
        return husband;
    }
 
    @Override
    public boolean equals(Object obj) {//myeclipse自动生成的
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Husband other = (Husband) obj;
        if (id != other.id)
            return false;
        return true;
    }
 
    /**
     * @param args
     * @throws CloneNotSupportedException 
     */
    public static void main(String[] args) throws CloneNotSupportedException {
        Wife wife = new Wife(1,"jin");
        Husband husband = new Husband(1);
        Husband husband2 = null;
        husband.setWife(wife);
        husband2 = (Husband) husband.clone();
        System.out.println("husband class same="+(husband.getClass()==husband2.getClass()));//true
        System.out.println("husband object same="+(husband==husband2));//false
        System.out.println("husband object equals="+(husband.equals(husband)));//true
        System.out.println("wife class same="+(husband.getWife().getClass()==husband2.getWife().getClass()));//true
        System.out.println("wife object same="+(husband.getWife()==husband2.getWife()));//false
        System.out.println("wife object equals="+(husband.getWife().equals(husband.getWife())));//true
    }
}

但是也有不足之处,如果Husband内有N个对象属性,突然改变了类的结构,还要重新修改clone()方法。解决办法:可以使用Serializable运用反序列化手段,调用java.io.ObjectInputStream对象的 readObject()方法。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个使用Cloneable接口和clone()方法的示例程序: ```java public class Person implements Cloneable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return this.name; } public void setAge(int age) { this.age = age; } public int getAge() { return this.age; } @Override public Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } } public class Main { public static void main(String[] args) { Person p1 = new Person("Tom", 20); try { Person p2 = p1.clone(); System.out.println("p1 name: " + p1.getName()); System.out.println("p1 age: " + p1.getAge()); System.out.println("p2 name: " + p2.getName()); System.out.println("p2 age: " + p2.getAge()); p2.setName("Jerry"); p2.setAge(25); System.out.println("p1 name: " + p1.getName()); System.out.println("p1 age: " + p1.getAge()); System.out.println("p2 name: " + p2.getName()); System.out.println("p2 age: " + p2.getAge()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } } } ``` 输出结果为: ``` p1 name: Tom p1 age: 20 p2 name: Tom p2 age: 20 p1 name: Tom p1 age: 20 p2 name: Jerry p2 age: 25 ``` 从输出结果可以看出,p1和p2都指向了不同的对象,但是它们的属性值是一样的。当修改p2的属性时,p1的属性值并没有改变。这是因为Java中的clone()方法会创建一个新的对象,但是不会调用构造方法。因此,我们需要实现Cloneable接口并且重写clone()方法来确保正确的克隆行为。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值