Java和PHP中的浅克隆和深克隆

在Java中,需要在被克隆的类上实现Cloneable接口,重写clone方法即可。浅克隆只能克隆类中基本数据类型以及String类型属性,不能克隆类中的引用类型属性。导致两个类中,同一个引用类型属性指向同一个引用对象。

如果在类的引用类型属性对应的类中,实现Cloneable接口,重写clone方法,就可以实现深拷贝

package fengliang.firstjava;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

class Employee implements Cloneable {
    protected String name;
    protected double salary;
    protected int id = assignId();
    protected static int nextId = 1;
    protected LocalDate hireDay;

    public Employee() {
    }

    public Employee(String var1, double var2, String var4) {
        this.name = var1;
        this.salary = var2;
        this.hireDay = LocalDate.parse(var4);
    }

    public Employee(String var1, double var2) {
        this.name = var1;
        this.salary = var2;
    }

    public String getHireDay() {
        return this.hireDay.format(DateTimeFormatter.ofPattern("y-MM-dd"));
    }

    public String getHireDay(String var1) {
        return this.hireDay.format(DateTimeFormatter.ofPattern(var1));
    }

    public String getName() {
        return this.name;
    }

    public final Employee setName(String var1) {
        this.name = var1;
        return this;
    }

    public final Employee setName() {
        return this;
    }

    public int getId() {
        return this.id;
    }

    protected static int assignId() {
        return nextId++;
    }

    public Employee clone() {
        Employee var1 = null;

        try {
            var1 = (Employee)super.clone();
        } catch (CloneNotSupportedException var3) {
            var3.printStackTrace();
        }

        return var1;
    }
}

class ShadowCopy <T extends Employee> implements Cloneable {

    private T employee;
    private String cardId;

    ShadowCopy() {}
    ShadowCopy(T employee, String cardId) {
        this.employee = employee;
        this.cardId = cardId;
    }

    public T getEmployee() {
        return employee;
    }

    public String getCardId() {
        return cardId;
    }

    public ShadowCopy<T> setEmployee(T employee) {
        this.employee = employee;
        return  this;
    }

    public ShadowCopy<T> setCardId(String cardId) {
        this.cardId = cardId;
        return  this;
    }
    
    //注意这里,浅拷贝
    @Override
    public ShadowCopy<T> clone() {
        try {
            return (ShadowCopy<T>) super.clone();
        } catch (CloneNotSupportedException exception) {
            return this;
        }
    }
}

class DeepCopy<T extends Employee> extends ShadowCopy<T> {

    DeepCopy(T employee, String cardId) {
        super(employee, cardId);
    }

    //注意这里,深拷贝。当注释clone.setEmployee((T)this.getEmployee().clone());后,它也是浅复制
    @Override
    public DeepCopy<T> clone() {
        DeepCopy<T> clone =  (DeepCopy<T>) super.clone();
        clone.setEmployee((T)this.getEmployee().clone());
        return clone;
    }
}

public class CloneTest {
    public static void main(String[] args) {
        Employee employee = new Employee("张三", 12);

        System.out.println("-------------------------------浅拷贝-------------------------------");
        ShadowCopy<Employee> shadowCopyObject = new ShadowCopy<Employee>(employee, "00001");
        ShadowCopy<Employee> clonedShadowCopyObject = shadowCopyObject.clone();
        clonedShadowCopyObject.setCardId("李四"+shadowCopyObject.getCardId()).getEmployee().setName("李四");
        System.out.println("原始shadowCopyObject对象中,Employee对象的name属性值为:"+shadowCopyObject.getEmployee().getName());
        System.out.println("clonedShadowCopyObject对象中,Employee对象的name属性值为:"+clonedShadowCopyObject.getEmployee().getName());
        System.out.println("原始shadowCopyObject对象中,CardId属性值为:"+shadowCopyObject.getCardId());
        System.out.println("clonedShadowCopyObject对象中,CardId属性值为:"+clonedShadowCopyObject.getCardId());

        System.out.println();

        System.out.println("-------------------------------深拷贝-------------------------------");
        Employee deepCopyEmployee = new Employee("王五", 13);
        DeepCopy<Employee> deepCopyObject = new DeepCopy<>(deepCopyEmployee, "00002");
        DeepCopy<Employee> clonedDeepCopyObject = deepCopyObject.clone();
        clonedDeepCopyObject.setCardId("赵六"+deepCopyObject.getCardId()).getEmployee().setName("赵六");
        System.out.println("原始deepCopyObject对象中,Employee对象的name属性值为:"+deepCopyObject.getEmployee().getName());
        System.out.println("clonedDeepCopyObject对象中,Employee对象的name属性值为:"+clonedDeepCopyObject.getEmployee().getName());
        System.out.println("原始deepCopyObject对象中,CardId属性值为:"+deepCopyObject.getCardId());
        System.out.println("clonedDeepCopyObject对象中,CardId属性值为:"+clonedDeepCopyObject.getCardId());
    }
}
View Code

在PHP中,使用clone关键字实现浅克隆,如果要实现深克隆,需要在类中实现__clone魔术方法

class Employee{
    protected $name;
    protected $id;
    protected static $nextId = 1;

    public function __construct(String $name)
    {
        $this->id = self::assignId();
        $this->name = $name;

    }

    protected static function assignId() : int
    {
        return self::$nextId++;
    }

    /**
     * @return String
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @param String $name
     */
    public function setName(string $name) : Employee
    {
        $this->name = $name;
        return $this;
    }

}

class ShadowClone {
    protected $employee;

    protected $cardId;

    public function __construct(Employee $employee, String $cardId)
    {
        $this->employee = $employee;
        $this->cardId = $cardId;
    }

    public function getCardId() : int {
        return $this->cardId;
    }

    /**
     * @return Employee
     */
    public function getEmployee(): Employee
    {
        return $this->employee;
    }
}

class DeepClone extends ShadowClone {
    
    function __clone()
    {
        //去掉这一行,就变成类浅克隆
        $this->employee = clone $this->employee;
    }
}

$employee = new Employee('张三');
$deepClone = new DeepClone($employee, '00001');
$cloneDeepClone = clone $deepClone;
$cloneDeepClone->getEmployee()->setName('李四');
echo $deepClone->getEmployee()->getName()."\r\n";
echo $cloneDeepClone->getEmployee()->getName();
View Code

 

 

posted on 2020-12-11 17:52  冯亮  阅读(106)  评论(0编辑  收藏  举报

导航