淺複製導致的bug

IAyue發表於2023-02-26

深複製與淺複製區別

在 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。

實現深複製的一些工具

相關文章