Java对象深拷贝的几种方式

对象拷贝

项目开发过程中很多时候需要进行对象复制,可是有的时候会发生复制后的对象,在原对象改变后也相应发生改变,这种时候就有问题了。所以很有必要了解对象的深拷贝,以及深拷贝的几种方式。

new 对象

手动 new 新的对象,一个属性一个属性的赋值,这种方式比较原始,也比较繁琐,容易出错,直接略过。

重载 clone()方法

对象中的基本类型是不需要考虑深拷贝的,深拷贝只针对对象类型或者对象集合对象。对于这种,可以分别重载对象中的clone方式

示例: OrderVO有三个字段

// (基本类型)
private String orderNo;
// (对象类型)
private UserVo userVo;
// (对象集合类型)
private List<GoodsVO> goodsVoList;   

OrderVo

package test.copy.vo;

import java.util.ArrayList;
import java.util.List;

public class OrderVO implements Cloneable{
    private String orderNo;

    private UserVO userVO;

    private List<GoodsVO> goodsVOList;

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public UserVO getUserVO() {
        return userVO;
    }

    public void setUserVO(UserVO userVO) {
        this.userVO = userVO;
    }

    public List<GoodsVO> getGoodsVOList() {
        return goodsVOList;
    }

    public void setGoodsVOList(List<GoodsVO> goodsVOList) {
        this.goodsVOList = goodsVOList;
    }

    @Override
    public OrderVO clone() {
        try {
            OrderVO orderVO = (OrderVO) super.clone();
            orderVO.setUserVO(this.userVO.clone());
            if (goodsVOList != null && goodsVOList.size() > 0) {
                List<GoodsVO> goodsList = new ArrayList<>();
                for (GoodsVO goodsVO : goodsVOList) {
                    goodsList.add(goodsVO.clone());
                }
                orderVO.setGoodsVOList(goodsList);
            }
            return orderVO;
        } catch (CloneNotSupportedException e) {
            System.out.println("exception happened");
        }
        return null;
    }
}

UserVo

package test.copy.vo;

public class UserVO implements Cloneable{
    private String userName;

    private int age;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }


    @Override
    public UserVO clone() {
        try {
            UserVO userVO = (UserVO) super.clone();
            return userVO;
        } catch (CloneNotSupportedException e) {
            System.out.println("exception happened");
        }
        return null;
    }
}

GoodsVo

package test.copy.vo;

import java.math.BigDecimal;

public class GoodsVO implements Cloneable{

    private String goodsName;

    private BigDecimal price;

    public String getGoodsName() {
        return goodsName;
    }

    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }


    @Override
    public GoodsVO clone() {
        try {
            GoodsVO userVO = (GoodsVO) super.clone();
            return userVO;
        } catch (CloneNotSupportedException e) {
            System.out.println("exception happened");
        }
        return null;
    }
}

测试类

package test.copy.vo;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class TestCopy {

    public static void main(String[] args) {
        OrderVO orderVO = new OrderVO();
        orderVO.setOrderNo("T0001001010");
        UserVO userVO = new UserVO();
        userVO.setUserName("Ellen Max");
        userVO.setAge(45);
        orderVO.setUserVO(userVO);
        List<GoodsVO> goodsVOList = new ArrayList<>();
        GoodsVO goodsVO1 = new GoodsVO();
        goodsVO1.setGoodsName("迪士尼门票");
        goodsVO1.setPrice(new BigDecimal("556"));

        GoodsVO goodsVO2 = new GoodsVO();
        goodsVO2.setGoodsName("东方明珠门票");
        goodsVO2.setPrice(new BigDecimal("125"));
        goodsVOList.add(goodsVO1);
        goodsVOList.add(goodsVO2);
        orderVO.setGoodsVOList(goodsVOList);

        OrderVO orderVO1 = orderVO.clone();
        System.out.println("clone success");

        orderVO.setOrderNo("A000123123");
        orderVO.getUserVO().setUserName("Steve Jobs");
        orderVO.getGoodsVOList().get(0).setGoodsName("香港迪士尼门票");
        System.out.println("改变原始orderVo");
        System.out.println("orderVO1.userVo.userName 没有改变");
        System.out.println("orderVO1.goodsVOList.get(0).goodsName 没有改变");
    }
}

JSON序列号

这种方式比较简单,就是对象转json字符串,再利用JSONObject转成对象,parseObject或者parseArray方法

Apache Commons Lang里面的SerializationUtils

这种方式有两点需要注意

  • 类都实现Serializable接口
  • 转换需要是同一种类,不通类之间无法转换,否则会报错

OrderDTO

package test.copy.vo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class OrderDTO implements Serializable {

    private String orderNo;

    private UserDTO userDTO;

    private List<GoodsDTO> goodsDTOList;

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public UserDTO getUserDTO() {
        return userDTO;
    }

    public void setUserDTO(UserDTO userDTO) {
        this.userDTO = userDTO;
    }

    public List<GoodsDTO> getGoodsDTOList() {
        return goodsDTOList;
    }

    public void setGoodsDTOList(List<GoodsDTO> goodsDTOList) {
        this.goodsDTOList = goodsDTOList;
    }
}

UserDTO

package test.copy.vo;

import java.io.Serializable;

public class UserDTO implements Serializable {
    private String userName;

    private int age;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

GoodsDTO

package test.copy.vo;

import java.io.Serializable;
import java.math.BigDecimal;

public class GoodsDTO implements Serializable {

    private String goodsName;

    private BigDecimal price;

    public String getGoodsName() {
        return goodsName;
    }

    public void setGoodsName(String goodsName) {
        this.goodsName = goodsName;
    }

    public BigDecimal getPrice() {
        return price;
    }

    public void setPrice(BigDecimal price) {
        this.price = price;
    }

}

Test


package test.copy.vo;

import org.apache.commons.lang3.SerializationUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

public class CommonsLangCopyTest {
    public static void main(String[] args) {
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setOrderNo("T0001001010");
        UserDTO userDTO = new UserDTO();
        userDTO.setUserName("Ellen Max");
        userDTO.setAge(45);
        orderDTO.setUserDTO(userDTO);
        List<GoodsDTO> goodsDTOList = new ArrayList<>();
        GoodsDTO goodsDTO1 = new GoodsDTO();
        goodsDTO1.setGoodsName("迪士尼门票");
        goodsDTO1.setPrice(new BigDecimal("556"));

        GoodsDTO goodsDTO2 = new GoodsDTO();
        goodsDTO2.setGoodsName("东方明珠门票");
        goodsDTO2.setPrice(new BigDecimal("125"));
        goodsDTOList.add(goodsDTO1);
        goodsDTOList.add(goodsDTO2);
        orderDTO.setGoodsDTOList(goodsDTOList);

        // 不需要指定class类型,因为只能为同一个类
        OrderDTO orderDTO1 = SerializationUtils.clone(orderDTO);
        System.out.println("clone success");


        orderDTO.setOrderNo("A000123123");
        orderDTO.getUserDTO().setUserName("Steve Jobs");
        orderDTO.getGoodsDTOList().get(0).setGoodsName("香港迪士尼门票");

        System.out.println("change source attribute");
    }
}

使用TypeReference

这个可以将任意json字符串转成成任意形式,如

  • 对象
  • List对象
  • Map<String, List>
	// 字符串转List<Object>
    List<ActuaryAssessmentReqDTO.Drug> drugList = JSONObject.parseObject(JSONObject.toJSONString(obj), new TypeReference<List<ActuaryAssessmentReqDTO.Drug>>() {});
    // 字符串转HashMap<String, List<List<ErrorInfo>>>
    Map<String, List<List<ErrorInfo>>> resultInfo = JSONObject.parseObject(obj, new TypeReference<HashMap<String, List<List<ErrorInfo>>>>() {});

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xinqing5130

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值