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()); } }
在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();