java拷贝_Java拷贝

Java 中的 clone 虽然不推荐使用,但是万一使用到还是有些地方需要注意的。

粗略介绍

Object 类中有个受保护方法 clone,所以很多时候我们都可以在类中重写 clone 方法。调用该方法会将对象复制一份,创造一个新的对象,但是这里就需要注意了。

Object 中存在 clone 方法,由于是受保护的,要使用对象的 clone 方法,还需要重写该方法,但是光是重写该方法并没用,还需要让 Java 虚拟机知道该类是支持 clone的,所以类需要实现 Cloneable 接口。

不实现 Cloneable 接口,而调用 clone 方法,会报错:

关于 clone ,最主要的应该还是浅拷贝和深拷贝。

浅拷贝

ShallowCopy.java

public class ShallowCopy implements Cloneable {

private String name;

private ArrayList list = new ArrayList<>();

public void printlnName() {

System.out.println(this.name);

}

public void setName(String name) {

this.name = name;

}

public void addListValue(String value) {

this.list.add(value);

}

public void printlnList() {

System.out.println(this.list);

}

public ShallowCopy() {

System.out.println("shallow copy test");

}

@Override

protected ShallowCopy clone() throws CloneNotSupportedException {

return (ShallowCopy) super.clone();

}

public static void main(String[] args) throws CloneNotSupportedException {

ShallowCopy shallow = new ShallowCopy();

shallow.setName("yhx");

shallow.addListValue("Java");

shallow.printlnName(); // 输出 yhx shallow.printlnList(); // 输出 Java

ShallowCopy shallowCopy = shallow.clone(); // 克隆 // 打印出两个对象的地址 System.out.println(shallow);

System.out.println(shallowCopy);

shallowCopy.printlnList(); // 输出 Java

shallowCopy.addListValue("Python");

shallowCopy.printlnList(); // 输出 Java,Python shallowCopy.printlnName(); // 输出 yhx

shallowCopy.setName("hello");

shallow.printlnName(); // 输出 yhx shallow.printlnList(); // // 输出 Java,Python }

}

从结果中我们可以看到拷贝时候虽然创建了新的对象,但是并没有调用构造方法

对象中的引用对象并没有拷贝,引用的地址还是和原对象一致

基本类型或者 String 默认会拷贝

像这种只拷贝了对象本身,而对象中引用数据类型没有被拷贝的拷贝方式,叫做浅拷贝。

浅拷贝往往存在一定的风险,因为引用对象的地址拷贝前后一致,所以对象的值很容易被更改,不安全。

深拷贝

将上面的代码简单修改下就成了深拷贝

DeepCopy.java

public class DeepCopy implements Cloneable{

private String name;

private ArrayList list = new ArrayList<>();

public void printlnName() {

System.out.println(this.name);

}

public void setName(String name) {

this.name = name;

}

public void addListValue(String value) {

this.list.add(value);

}

public void printlnList() {

System.out.println(this.list);

}

public DeepCopy() {

System.out.println("deep copy test");

}

@Override

protected DeepCopy clone() throws CloneNotSupportedException {

DeepCopy clone = (DeepCopy) super.clone();

clone.list = (ArrayList) this.list.clone();

return clone;

}

public static void main(String[] args) throws CloneNotSupportedException {

DeepCopy deep = new DeepCopy();

deep.setName("yhx");

deep.addListValue("Java");

deep.printlnName();

deep.printlnList();

DeepCopy DeepCopy = deep.clone(); // 克隆 // 打印出两个对象的地址 System.out.println(deep);

System.out.println(DeepCopy);

DeepCopy.printlnList();

DeepCopy.addListValue("Python");

DeepCopy.printlnList();

DeepCopy.printlnName();

DeepCopy.setName("hello");

deep.printlnName();

deep.printlnList();

}

}

打印结果:

可以看到,原先对象中 list 的值并不会因为拷贝对象的 list 值改变而改变,因为它们存于两个不同的内存了,不会共享。

Note:

如果字段上有 final 修饰,就不能实现 clone 方法了,因为 final 变量不能再次被赋值。

应用场景

原型模式中会使用到拷贝。

作者: Be a funny man

转载请注明出处

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值