深拷贝和浅拷贝

深拷贝和浅拷贝

cloneable

clone() 是 Object 的 protected ⽅法,⼀个类不显式去重写 clone(),其它类就不能直接去调⽤该类实例的 clone() ⽅法。

public class CloneExample {
 private int a;
 private int b; }
CloneExample e1 = new CloneExample();
// CloneExample e2 = e1.clone(); // 'clone()' has protected access in'java.lang.Object'

重写 clone() 得到以下实现:

public class CloneExample {
 private int a;
 private int b;
 @Override
 public CloneExample clone() throws CloneNotSupportedException {
 return (CloneExample)super.clone();
 }
}
CloneExample e1 = new CloneExample();
try {
 CloneExample e2 = e1.clone();
} catch (CloneNotSupportedException e) {
 e.printStackTrace();
}
java.lang.CloneNotSupportedException: CloneExample

以上抛出了 CloneNotSupportedException,这是因为 CloneExample 没有实现 Cloneable 接⼝。应该注意的是,clone() ⽅法并不是 Cloneable 接⼝的⽅法,⽽是 Object 的⼀个 protected ⽅法。 Cloneable 接⼝只是规定,如果⼀个类没有实现 Cloneable 接⼝⼜调⽤了 clone() ⽅法,就会抛出 CloneNotSupportedException。

public class CloneExample implements Cloneable {
 private int a;
 private int b;
 @Override
 public Object clone() throws CloneNotSupportedException {
 return super.clone();
 }
}

基本类型和引用类型在内存上存储的区别

img

  1. 定义局部变量 age,由于age是局部变量,所以在栈中申请内存空间,起名为age,又由于给age赋的值250是基本类型,所以,值直接存储在栈中。
  2. 定义局部变量arr,由于arr是局部变量,所以在栈中申请空间,但是arr的内存中存储的是什么?由于给arr赋的值不是基本类型,而是引用类型(new出来的),所以,先在堆中申请空间存放数据 12,23,34,。再把堆区的地址赋给arr。

浅拷⻉

浅拷⻉:就是把栈中的数据拷贝一份,即拷⻉对象和原始对象的引⽤类型引⽤同⼀个对象基本数据类型各自有一份

public class ShallowCloneExample implements Cloneable {
 private int[] arr;
 public ShallowCloneExample() {
 arr = new int[10];
 for (int i = 0; i < arr.length; i++) {
 arr[i] = i;
   }
 }
 public void set(int index, int value) {
 arr[index] = value;
 }
 public int get(int index) {
 return arr[index];
 }
 @Override//浅拷⻉
 protected ShallowCloneExample clone() throws CloneNotSupportedException
{
 return (ShallowCloneExample) super.clone();
 }
}
ShallowCloneExample e1 = new ShallowCloneExample();
ShallowCloneExample e2 = null;
try {
 e2 = e1.clone();
} catch (CloneNotSupportedException e) {
 e.printStackTrace();
}
e1.set(2, 222);
System.out.println(e2.get(2)); // 222
  1. 深拷⻉

深拷⻉:拷⻉对象和原始对象的引⽤类型引⽤不同对象。即再浅拷贝的基础上,将所有非基本数据类型的属性,手动拷贝一份

public class DeepCloneExample implements Cloneable {
 private int[] arr;
 public DeepCloneExample() {
 arr = new int[10];
 for (int i = 0; i < arr.length; i++) {
 arr[i] = i;
  }
 }
 public void set(int index, int value) {
 arr[index] = value;
 }
 public int get(int index) {
 return arr[index];
 }
 @Override//深拷贝,将所有非基本数据类型的属性,手动拷贝一份。即int[] arr
 protected DeepCloneExample clone() throws CloneNotSupportedException {
 DeepCloneExample result = (DeepCloneExample) super.clone();
 result.arr = new int[arr.length];
 for (int i = 0; i < arr.length; i++) {
 result.arr[i] = arr[i];
 }
 return result;
 }
}
DeepCloneExample e1 = new DeepCloneExample();
DeepCloneExample e2 = null;
try {
 e2 = e1.clone();
} catch (CloneNotSupportedException e) {
 e.printStackTrace();
}
e1.set(2, 222);
System.out.println(e2.get(2)); // 2

clone()的替代⽅案

使⽤ clone() ⽅法来拷⻉⼀个对象即复杂⼜有⻛险,它会抛出异常,并且还需要类型转换。Effective Java 书上讲到,最好不要使⽤ clone(),可以使⽤拷⻉构造函数或者拷⻉⼯⼚来拷⻉⼀个对象。 即通过传入一个实例对象,手动拷贝它

public class CloneConstructorExample {
 private int[] arr;
 public CloneConstructorExample() {
 arr = new int[10];
 for (int i = 0; i < arr.length; i++) {
 arr[i] = i;
 }
 }
  //拷贝构造函数, 一个实例对象,手动拷贝它
 public CloneConstructorExample(CloneConstructorExample original) {
 arr = new int[original.arr.length];
 for (int i = 0; i < original.arr.length; i++) {
 arr[i] = original.arr[i];
 }
 }
 public void set(int index, int value) {
 arr[index] = value;
 }
 public int get(int index) {
 return arr[index];
 }
}
CloneConstructorExample e1 = new CloneConstructorExample();
CloneConstructorExample e2 = new CloneConstructorExample(e1);
e1.set(2, 222);
System.out.println(e2.get(2)); // 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值