广告
返回顶部
首页 > 资讯 > 后端开发 > JAVA >java中关于深拷贝的几种方式
  • 325
分享到

java中关于深拷贝的几种方式

javajvm开发语言 2023-08-31 05:08:58 325人浏览 独家记忆
摘要

在java里,当我们需要拷贝一个对象时,有两种类型的拷贝:浅拷贝与深拷贝。 浅拷贝只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。深拷贝则是拷贝了源对象的所有值,所以即使源对象的值发生变化时,拷贝对象的值也不会改

在java里,当我们需要拷贝一个对象时,有两种类型的拷贝:浅拷贝与深拷贝。

  • 浅拷贝只是拷贝了源对象的地址,所以源对象的值发生变化时,拷贝对象的值也会发生变化。
  • 深拷贝则是拷贝了源对象的所有值,所以即使源对象的值发生变化时,拷贝对象的值也不会改变。

方式1:构造函数深拷贝

package com.lyj.demo.pojo.cloneTest;import lombok.Getter;@Getterpublic class UserConstruct {    private String userName;    private AddressConstruct address;    public UserConstruct() {    }    public UserConstruct(String userName, AddressConstruct address) {        this.userName = userName;        this.address = address;    }    public static void main(String[] args) {        AddressConstruct address = new AddressConstruct("小区1", "小区2");        UserConstruct user = new UserConstruct("小李", address);        // 调用构造函数进行深拷贝        UserConstruct copyUser = new UserConstruct(user.getUserName(), new AddressConstruct(address.getAddress1(), address.getAddress2()));        // 修改源对象的值        user.getAddress().setAddress1("小区3");        // false        System.out.println(user == copyUser);        // false        System.out.println(user.getAddress().getAddress1() == copyUser.getAddress().getAddress1());        // false        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));        // true        System.out.println(user.getAddress().getAddress2().equals(copyUser.getAddress().getAddress2()));    }}package com.lyj.demo.pojo.cloneTest;import lombok.Getter;import lombok.Setter;@Getter@Setterpublic class AddressConstruct {    private String address1;    private String address2;    public AddressConstruct() {    }    public AddressConstruct(String address1, String address2) {        this.address1 = address1;        this.address2 = address2;    }}

方式2:重载Clone()方法深拷贝

Object父类有个clone()的拷贝方法,不过它是protected类型的 ,我们需要重写它并修改为public类型,除此之外,子类还需要实现Cloneable接口来告诉JVM这个类上是可以拷贝的。

package com.lyj.demo.pojo.cloneTest;import lombok.Getter;import lombok.Setter;@Setter@Getterpublic class AddressClone implements Cloneable{    private String address1;    private String address2;    public AddressClone() {    }    public AddressClone(String address1, String address2) {        this.address1 = address1;        this.address2 = address2;    }    @Override    protected AddressClone clone() throws CloneNotSupportedException {        return (AddressClone) super.clone();    }}package com.lyj.demo.pojo.cloneTest;import lombok.Getter;import lombok.Setter;@Setter@Getterpublic class UserClone implements Cloneable{    private String userName;    private AddressClone address;    public UserClone() {    }    public UserClone(String userName, AddressClone address) {        this.userName = userName;        this.address = address;    }        @Override    protected UserClone clone() throws CloneNotSupportedException {        // 需要注意的是,super.clone()其实是浅拷贝,        // 所以在重写UserClone类的clone()方法时,address对象需要调用address.clone()重新赋值        UserClone userClone = (UserClone) super.clone();        userClone.setAddress(this.address.clone());        return userClone;    }    public static void main(String[] args) throws CloneNotSupportedException {        AddressClone address = new AddressClone("小区1", "小区2");        UserClone user = new UserClone("小李", address);        UserClone copyUser = user.clone();        user.getAddress().setAddress1("小区3");        // false        System.out.println(user == copyUser);        // false        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));    }}

需要注意的是,super.clone()其实是浅拷贝,所以在重写User类的clone()方法时,address对象需要调用address.clone()重新赋值。

方式3:Apache Commons Lang序列化方式深拷贝

Java提供了序列化的能力,我们可以先将源对象进行序列化,再反序列化生成拷贝对象。但是,使用序列化的前提是拷贝的类(包括其成员变量)需要实现Serializable接口。

Apache Commons Lang包对Java序列化进行了封装,我们可以直接使用它。

package com.lyj.demo.pojo.cloneTest;import lombok.Getter;import lombok.Setter;import java.io.Serializable;@Getter@Setterpublic class AddressSerializable implements Serializable {    private String address1;    private String address2;    public AddressSerializable() {    }    public AddressSerializable(String address1, String address2) {        this.address1 = address1;        this.address2 = address2;    }}package com.lyj.demo.pojo.cloneTest;import lombok.Getter;import lombok.Setter;import org.apache.commons.lang3.SerializationUtils;import java.io.Serializable;@Getter@Setterpublic class UserSerializable implements Serializable {    private String userName;    private AddressSerializable address;    public UserSerializable() {    }    public UserSerializable(String userName, AddressSerializable address) {        this.userName = userName;        this.address = address;    }    public static void main(String[] args) {        AddressSerializable address = new AddressSerializable("小区1", "小区2");        UserSerializable user = new UserSerializable("小李", address);        UserSerializable copyUser = SerializationUtils.clone(user);        user.getAddress().setAddress1("小区3");        // false        System.out.println(user == copyUser);        // false        System.out.println(user.getAddress().getAddress1().equals(copyUser.getAddress().getAddress1()));    }}

来源地址:https://blog.csdn.net/wsb8233696/article/details/130907780

--结束END--

本文标题: java中关于深拷贝的几种方式

本文链接: https://www.lsjlt.com/news/383931.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作