对象克隆----Cloneable接口

2018-11-18  本文已影响0人  爱做梦的严重精神病患者

默认的clone方法是Object的一个protected方法不能在其他类中直接调用需要实现Cloneable接口默认的克隆操作是“浅拷贝”,并没有克隆原对象引用的其他对象

 如果对象中的所有数据域是数值其他基本类型,拷贝这些域没有任何问题。但是如果对象包含其他对象的引用拷贝域就会得到相同的其他对象的另一个引用,这样一来原对象和克隆的对象仍然共享一些信息

 如果原对象和浅克隆对象共享的对象域是不可变的(属于不可变类,例:String类),那么这种共享就是安全的。或者在对象的生命周期中,对象域一直包含不变的常量没有更改器会改变它,也没有方法会生成它的引用,同样也是安全的。

 不过,通常对象域都是可变的,必须重新定义clone方法来建立一个深度拷贝,同时克隆所有对象域

 对于每一个类,使用clone需要:


 默认的浅度拷贝(克隆):实现Cloneable接口,将clone重新定义为public,再调用super.clone()

public class Employee implements Cloneable {
    public Employee clone() throws CloneNotSupportedException {
        return (Employee) super.clone();
    }
}

深度拷贝(克隆):克隆所有对象域

public class Employee implements Cloneable {
    private String name;
    private double salary;
    private Date hireDay;

    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
        hireDay = new Date();
    }

    public Employee clone() throws CloneNotSupportedException {
        Employee cloned = (Employee) super.clone();
        //Date类已实现Cloneable接口
        cloned.hireDay = (Date) hireDay.clone();
        
        return cloned;
    }
    
    public void setHireDay(int year, int month, int day) {
        Date newHireDay = new GregorianCalendar(year, month-1, day).getTime();
        hireDay.setTime(newHireDay.getTime());
    }
    
    public void raiseSalary(double byPercent) {
        double raise = salary * byPercent / 100;
        salary += raise;
    }

}

注意子类的克隆。例如,一旦为Employee类定义了clone方法,任何人都可以利用它来克隆Manager对象(Manager extends Employee)。Employee.clone()不能百分百完成工作,这要取决于Manager类的域

不能保证子类的实现者一定会修正clone方法,让它正常工作。

上一篇下一篇

猜你喜欢

热点阅读