浅拷贝与深拷贝的主要区别在于对象属性的复制方式。浅拷贝只复制对象的直接属性,如果属性是基本类型,则复制其值;如果属性是引用类型,则复制引用,而不是复制引用的对象本身。深拷贝则复制对象的所有属性,包括引用类型属性的副本。
Java中的实例
易错浅拷贝实例
在Java中,如果不正确地实现clone
方法,可能会导致浅拷贝。
public class Address {
private String street;
// 忽略构造函数、getter和setter
}
public class Person implements Cloneable {
private String name;
private Address address;
// 忽略构造函数、getter和setter
@Override
protected Object clone() throws CloneNotSupportedException {
// 错误的浅拷贝实现,没有复制Address对象
return super.clone();
}
}
Person original = new Person("John", new Address("123 Main St"));
Person copy = (Person) original.clone();
original.getAddress().setStreet("456 Elm St");
// 浅拷贝,共享Address对象,输出:456 Elm St
System.out.println(copy.getAddress().getStreet());
正确的深拷贝写法
在Java中,正确的深拷贝需要确保所有引用类型属性都被正确复制。
public class Address implements Cloneable {
private String street;
// 忽略构造函数、getter和setter
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Person implements Cloneable {
private String name;
private Address address;
// 忽略构造函数、getter和setter
@Override
protected Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone();
cloned.address = (Address) address.clone(); // 正确的深拷贝
return cloned;
}
}
Person original = new Person("John", new Address("123 Main St"));
Person copy = (Person) original.clone();
original.getAddress().setStreet("456 Elm St");
// 深拷贝,Address对象是独立的,输出:123 Main St
System.out.println(copy.getAddress().getStreet());
JavaScript中的实例
易错浅拷贝实例
在JavaScript中,使用Object.assign
或扩展运算符(...
)进行浅拷贝时,需要注意引用类型属性的问题。
const original = {
name: 'John',
address: { street: '123 Main St' }
};
// 使用Object.assign进行浅拷贝
const copy = Object.assign({}, original);
original.address.street = '456 Elm St';
// 浅拷贝,共享address对象,输出:456 Elm St
console.log(copy.address.street);
正确的深拷贝写法
在JavaScript中,可以使用JSON.parse(JSON.stringify(obj))
来实现深拷贝,但要注意它不能处理函数和循环引用。
const original = {
name: 'John',
address: { street: '123 Main St' }
};
// 使用JSON方法进行深拷贝
const copy = JSON.parse(JSON.stringify(original));
original.address.street = '456 Elm St';
// 深拷贝,address对象是独立的,输出:123 Main St
console.log(copy.address.street);
请注意,JSON.parse(JSON.stringify(obj))
方法并不是万能的,它不能处理复杂的对象,例如包含函数、循环引用或者特殊对象(如Date
、RegExp
等)的对象。在这种情况下,可能需要使用库如lodash
的_.cloneDeep
方法来实现深拷贝。