java中对象拷贝的几种方式

方式一

实现Cloneable接口,重写clone()方法

示例对象

@Data
public class User implements Cloneable,Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private List list = new ArrayList<String>();


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

}

分析:使用clone()方法进行拷贝,这种方法的优点是可以直接使用父接口的clone()方法直接拷贝一个对象,同时能够拷贝基本数据类型,但是引用数据类型不能拷贝,原对象和拷贝对象的引用属性是同一个属性,这种拷贝也就是常说的浅拷贝,测试如下

@Test
    public void testNewInstance() throws IllegalAccessException, InstantiationException {
        User user = new User();
        user.setName("111");
        User clone = user.clone();
        List list = user.getList();
        //给原对象中的list进行赋值
        list.add("hello");
        //获取拷贝对象的list属性
        List cloneList = clone.getList();
        Object o = cloneList.get(0);
        System.out.println(clone.getName());//输出为111
        System.out.println(o.toString());//输出结果为hell0,说明引用的是同一个ArrayList对象
    }

方式二

使用序列化,拷贝对象实现Serializable接口,并写入serialVersionUID 

分析:能够完整的拷贝对象,包括引用类型属性,但是需要自己写序列化过程,测试如下

 @Test
    public void testSerializable() throws Exception {
        User user = new User();
        user.setName("111");
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(user);
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        User cloneUser = (User) objectInputStream.readObject();
        List list = user.getList();
        list.add("hello");
        List cloneUserList = cloneUser.getList();
        System.out.println(cloneUserList.size());//输出为0,说明原对象list属性的改变对克隆对象的引用属性无影响,也就是不是引用的同一个对象,拷贝成功
        System.out.println(cloneUser.getName());//输出111,拷贝成功

    }

注意:为什么要写入serialVersionUID,主要是用于反序列化,如果没有唯一的UID,一旦原类结构发生了改变,则无法进行反序列化

猜你喜欢

转载自blog.csdn.net/ly853602/article/details/84679885