java 浅拷贝和深拷贝
java 浅拷贝和深拷贝
简单理解:
浅拷贝:拷贝地址。原变量改变,新变量也会受到影响
深拷贝:拷贝值,开辟一块新的内存返回。原变量改变,新变量不会受到影响
拷贝基本数据类型
拷贝基本数据类型字面量,都是拷贝值
拷贝引用类型
浅拷贝:
-
直接赋值,直接返回的是克隆对象的引用地址
测试代码:
public class User { public User(Integer age) { this.age = age; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } private Integer age; public static void main(String[] args) { User user = new User(10); User user2 = user; user2.setAge(100); System.out.println(user == user2); // true System.out.println(user.getAge()); // 100 } }
-
Cloneable接口
测试代码:public class User implements Cloneable { @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } private Integer age; private String name; private int height; private Son son; public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public Son getSon() { return son; } public void setSon(Son son) { this.son = son; } public User(Integer age, String name, int height, Son son) { this.age = age; this.name = name; this.height = height; this.son = son; } public static void main(String[] args) throws CloneNotSupportedException { User user = new User(10, "name", 180, new Son("xxx")); User user2 = (User) user.clone(); user2.getSon().setName("yyy"); System.out.println(user.getSon() == user2.getSon()); // true System.out.println(user.getSon().getName()); // yyy } }
深拷贝:
- Cloneable的clone其实只能拷贝一层(就是和直接赋值不相同的是,user = user2,user和user2地址一样,clone是user和user2的地址不一样,user和user2里面的第一层也不一样,再深入就全是一样的),如果我们重写clone,遍历层级进行clone就可达到深拷贝
- 各种序列化拷贝,例如:JSON序列化,Object序列化流,需要实现Serializable接口,速度相对慢
注意点:被transient修饰不参与序列化
不可变类的特殊性:
例如像这种String、包装类,这种都是不可变类,它们不能改变内容,如果要改变,是开辟新的内存,返回地址,而不是改变内存里的数据,所以不可变类的拷贝都是引用的地址