引用拷贝、浅拷贝、深拷贝
当我们想复制一个对象时,最自然的操作就是直接赋值给另一个变量,这种做法只是,复制了对象的地址,两个变量指向了同一个对象,任意一个变量操作对象的属性,都会影响到另一个变量。 (如下)
Person p1 = new Person(17);
Person p2 = p1; // 直接赋值
p2.age = 20; // 使用 p2 给属性赋值
System.out.println(p1 = p2); // true
System.out.println(p1.age); // 20
这种对同一个对象的操作,当然算不上复制。(所以,引用拷贝并不算是对象拷贝)
我们一般说的对象拷贝,就是指,浅拷贝 和 深拷贝。
先说浅拷贝
public class Object {
protected native Object clone() throws CloneNoSupportedExpection;
}
Object 提供了一个 clone() ,
看名字就知道,它和对象拷贝有关,
该方法的访问修饰符为 protected,
如果子类不重写该方法,并将其声明为 public ,那外部就调用不了,对象的 clone(),
子类在重写时直接调用,Object 的 clone()
public class Demo01 {
public int age;
public Demo01() {
}
public Demo01(int age) {
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// 调用
public static void main(String[] args) throws CloneNotSupportedException {
Demo01 d1 = new Demo01(18);
Demo01 clone = (Demo01)d1.clone();
d1.age = 20;
}
}
它是 native 方法,底层已经实现了拷贝对象的逻辑,
这里要注意,子类一定要实现 Cloneable 接口,
否则在调用 clone() 时,就会抛出异常,这是 java 的规定。
现在我们就可以调用 clone() 方法 来复制对象了。
Person p1 = new Person(18);
Person p2 = new Person();
p2.age = 20;
System.out.println(p1 = p2); // false
System.out.println(p1.age); // 18
此时,会发现,两个对象指向的是两个不同的对象,各自改变属性,也不会影响到另一个对象,
看起来效果很好,但是有一个问题:如果拷贝的对象中,有属性是引用类型,那这种浅拷贝的方式
public class Person implements Cloneable {
public int age;
public int[] arr = new int[]{1,2};
public Person() {
}
public Person(int age, int[] arr) {
this.age = age;
this.arr = arr;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
只是会复制该属性的引用地址,即拷贝对象和原对象,都指向了同一个引用类型(对象)
如果对这个属性,进行一些操作,则会影响到另一个对象的属性。
若是想将对象中的引用类型属性也进行拷贝。
那就需要用到 深拷贝了。
简单将代码修改一下
@Override
protected Object clone() throws CloneNotSupportedException {
Person person = (Person) super.clone();
person.arr = this.arr.clone();
return person;
}
克隆出对象之后,然后再对引用类型的属性进行复制。
此时,对象中的属性也指向了不同的实例
引用拷贝、浅拷贝、深拷贝之间的区别!
区别 | |
---|---|
引用拷贝 | 只是复制对象的地址,并不会创建一个新对象。 |
浅拷贝 | 会创建一个新对象,并进行属性的复制。但是对引用类型的属性,只会复制其地址。 |
深拷贝 | 完全复制整个对象,包括引用类型的对象。 |
实际开发中,不建议使用,因为有抛出异常的风险,如果真想让对象提供拷贝功能,那就自己编写吧!
作者:走马
出处:https://www.cnblogs.com/zou-ma/p/16188080.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
本博文版权归本博主所有,未经授权不得转载
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律