Java对象复制/复制对象

本文探讨了在实际业务中复制对象的常见需求,比较了实现Cloneable接口、序列化和BeanUtils工具复制对象的优劣,并通过实例展示了如何使用这些方法。特别关注了clone方法的高效性和BeanUtils的反射机制效率。
摘要由CSDN通过智能技术生成

使用场景

  • 在实际的业务使用场景中我们会碰到复制对象的需求,例如财务场景中,系统之间集成,需要传凭证给财务系统,这里就会有借方数据和贷方数据,通常我们会将借方数据塞到一个对象中,贷方数据塞到一个对象中,在粘贴复制代码时你会发现,借方数据和贷方数据之间的差别可能就几个字段不同,代码写完交付了,项目经理突然提出要修改一个字段传的数据,去翻看代码时发现借方对象和贷方对象都有这个字段,需要改好几个地方。这个时候我们就想要是能复制对象就好了,这样我修改就只要修改一个对象,后面的全自动完成,减少代码的维护工作量。

三种复制方法

  • 实现Cloneable接口,重写clone方法
  • 序列化
  • 使用BeanUtils工具类复制对象

代码示例

  • 这里我按照三种方法的顺序附上相应的示例代码。
实现Cloneable接口,重写clone方法
  • 创建一个Car类,此类实现了Cloneable接口,重写了clone方法
public class Car implements Cloneable {
    private String brand;
    private int price;

    public int getPrice() {
        return price;
    }

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

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    @Override
    public Car clone() {
        try {
            return (Car) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}
  • 测试复制代码如下,先复制一个Car对象,再修改原来的对象,可以检测出是否真的复制成功了,而不是只有对象的引用
public class Test {

    public static void main(String[] args){
        Car car = new Car();
        car.setBrand("奥迪A6");
        car.setPrice(45);
        Car cloneCar = car.clone();
        car.setPrice(11);
        System.out.println(cloneCar.toString());
    }

}
序列化
  • Java中常见的序列化方式是实现Serializable接口,示例代码如下
public class Car implements Serializable {
    private String brand;
    private int price;

    public int getPrice() {
        return price;
    }

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

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}
  • 测试代码如下,主要思想是先将对象转成流,再将流转成对象,这么一进一出,对象已经不是原来的对象了,赋予了新的生命
public class Test {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Car car = new Car();
        car.setBrand("奥迪A6");
        car.setPrice(45);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);
        outputStream.writeObject(car);

        byte[] bytes = byteArrayOutputStream.toByteArray();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Car cloneCar = (Car) objectInputStream.readObject();
        System.out.println(cloneCar.toString());
    }

}
使用BeanUtils工具类复制对象
  • 创建一个普通的类,这里不用继承什么类,也不用实现什么接口,就是最普通的类,随心所欲
public class Car{
    private String brand;
    private int price;

    public int getPrice() {
        return price;
    }

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

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", price=" + price +
                '}';
    }
}
  • 测试代码如下,使用org.springframework.beans包下的BeanUtils的copyProperties方法就可以实现复制对象
public class Test {

    public static void main(String[] args) {
        Car car = new Car();
        car.setBrand("奥迪A6");
        car.setPrice(45);
        Car cloneCar = new Car();
        BeanUtils.copyProperties(car, cloneCar);
        System.out.println(cloneCar.toString());
    }

}

总结

  • 上述三种方法中,我在项目中常用到的是第一种和第三种方法,出于对代码效率上的好奇,我后来写了一个示例计算了下第一种方法和第三种方法的效率,使用第一种方法和第三种方法复制100万个对象出来,耗时如下,从下面可以看出clone的效率远远高于copyProperties,大家可以翻看源码,可以发现clone最终调用的是native方法,而copyProperties是采用的反射的方式。
方法名称耗时(ms)
重写clone()方法45
使用BeanUtils.copyProperties方法1671
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值