浅拷贝导致的bug

时间:2023-02-26 11:07:17

深拷贝与浅拷贝区别

在 Java 中,除了基本数据类型(元类型)之外,还存在类的实例对象这个引用数据类型。而一般使用 『 = 』号做赋值操作的时候。对于基本数据类型,实际上是拷贝的它的值,但是对于对象而言,其实赋值的只是这个对象的引用,将原对象的引用传递过去,他们实际上还是指向的同一个对象。
而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象,,则认为是浅拷贝。反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。

hutool BeanUtil.copyProperties 浅拷贝问题重现

    @Test
    public void testCopy(){

        Student.Transcript transcript =  Student.Transcript.builder().score(100).build();
        Student student = Student.builder().id(1).transcript(transcript).build();

        System.out.println("student = " + student);

        Student copyStudent = BeanUtil.copyProperties(student,Student.class);

        System.out.println("copyStudent = " + copyStudent);

        Student.Transcript studentTranscript =  student.getTranscript();
        studentTranscript.setScore(99);
        student.setId(2);

        System.out.println("student = " + student);
        System.out.println("copyStudent = " + copyStudent);
    }

    @Builder
    @Data
    static class Student{
        Integer id;

        Transcript transcript;

        @Builder
        @Data
        static class Transcript{
            int score;
        }
    }

执行结果

student = Student(id=1, transcript=Student.Transcript(score=100))
copyStudent = Student(id=1, transcript=Student.Transcript(score=100))
student = Student(id=2, transcript=Student.Transcript(score=99))
copyStudent = Student(id=1, transcript=Student.Transcript(score=99))

在代码中,我们对原有的student实例进行了两个修改,分别是id赋值为2,student内的transcript score重新赋值。
从执行结果可以看到,在对student实例Transcript对象进行修改后,复制得到的copyStudent也发生了相应的变动,但copyStudent的id仍然是1,没有跟随student的id。

实现深拷贝的一些工具