[JAVA] Shallow Copy กับ Deep Copy

จากบทความที่แล้วนะครับ จะเป็นการใช้แนวคิด Shallow Copy กับ Deep Copy ใน .Net Framework ภาษา C# ครับ คราวนี้มาถึงตาม Java บ้างครับ

เปิดมาที่ Code เลยครับ

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

class Person implements Cloneable {
    private String name;
    private List<String> nicknames;

    public Person(String name) {
        this.name = name;
        this.nicknames = new ArrayList<>();
    }

    public void addNickname(String nickname) {
        this.nicknames.add(nickname);
    }

    public List<String> getNicknames() {
        return nicknames;
    }

    // Shallow Copy
    public Person shallowCopy() throws CloneNotSupportedException {
        return (Person) super.clone();
    }

    // Deep Copy
    public Person deepCopy() {
        Person clonedPerson = new Person(this.name);
        for (String nickname : this.nicknames) {
            clonedPerson.addNickname(new String(nickname));
        }
        return clonedPerson;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + '\'' + ", nicknames=" + nicknames + '}';
    }
}

public class DeepCopyVsShallowCopy {
    public static void main(String[] args) throws CloneNotSupportedException {
        Person original = new Person("Chatri");
        original.addNickname("ping");
        original.addNickname("pingkung");

        // Shallow copy
        Person shallowCopied = original.shallowCopy();
        shallowCopied.getNicknames().add("naiwaen");

        // Deep copy
        Person deepCopied = original.deepCopy();
        deepCopied.getNicknames().add("CN");

        System.out.println("Original: " + original);
        System.out.println("Shallow Copied: " + shallowCopied);
        System.out.println("Deep Copied: " + deepCopied);
    }
}

ใน Blog ผมเตรียม Class Person ไว้ โดยมี Get / Set ปกติ และทำ

  • Shallow Copy ใน Method shallowCopy อันนี้ผมใช้ความสามารถของ Cloneable เข้ามาช่วยครับ
// Shallow Copy
public Person shallowCopy() throws CloneNotSupportedException {
   return (Person) super.clone();
}

จริงๆ ถ้าไม่อยากเขียนแบบนี้มันมีตัว BeanUtils.copyProperties ที่ช่วยทำ Shallow Copy ให้ครับ แต่มันมีความพิสดารของ Spring / Apache Common Param มันจะสลับกันครับ

Ref: https://stackoverflow.com/a/34988281

  • Deep Copy อันนี้ใช้วิํธี New Object แล้ว Loop ยัดค่าใหม่ ได้คนละ Reference แน่ๆครับ
// Deep Copy
public Person deepCopy() {
   Person clonedPerson = new Person(this.name);
   for (String nickname : this.nicknames) {
      clonedPerson.addNickname(new String(nickname));
   }
   return clonedPerson;
}

Result

  • ตรง original จริงถ้าดูจาก Code มันจะยัด nicknames แต่ 2 ตัว ping, pingkung เท่านั้นครับ แต่เนื่องจากเป็น Shallow Copy ไปที่ shallowCopied เลยแก้ค่าได้ ตอน Print เลยมี naiwaen โผลขึ้นมา
  • ส่วน deepCopied อันนี้ มันตั้งต้น 3 อันอยู่แล้ว ตัว Original โดน Shallow Copy เติมค่าไป
    แล้วที่นี้มีเติมค่า CN ต่อไปอีกนั้น แต่เนื่องจากมันเป็น Deep copy มันเลยไม่ Effect ไป shallowCopied / original
Original: Person{name='Chatri', nicknames=[ping, pingkung, naiwaen]}
Shallow Copied: Person{name='Chatri', nicknames=[ping, pingkung, naiwaen]}
Deep Copied: Person{name='Chatri', nicknames=[ping, pingkung, naiwaen, CN]}


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts sent to your email.