วัตถุที่ไม่เปลี่ยนรูป คืออ็อบเจ็กต์ที่สถานะ ไม่สามารถเปลี่ยนแปลงได้เมื่อเริ่มต้น . บางครั้งจำเป็นต้องสร้างคลาสที่ไม่เปลี่ยนรูปตามความต้องการ ตัวอย่างเช่น คลาส wrapper ดั้งเดิมทั้งหมด (Integer, Byte, Long, Float, Double, Character, Boolean และ Short) จะไม่เปลี่ยนรูปแบบใน Java คลาสสตริง ยังเป็นคลาสที่ไม่เปลี่ยนรูปอีกด้วย
ในการสร้างคลาสที่ไม่เปลี่ยนรูปแบบที่กำหนดเอง เราต้องทำตามขั้นตอนต่อไปนี้
- ประกาศคลาสเป็น สุดท้าย เลยขยายไม่ได้
- กำหนดให้ฟิลด์ทั้งหมดเป็นส่วนตัว เพื่อไม่ให้เข้าถึงโดยตรง
- อย่าให้วิธีตั้งค่า (เมธอดที่ปรับเปลี่ยนฟิลด์) สำหรับตัวแปร เพื่อไม่ให้ตั้งค่าได้
- ทำให้ ฟิลด์ที่เปลี่ยนแปลงได้ทั้งหมด เพื่อให้สามารถกำหนดค่าได้เพียงครั้งเดียว
- เริ่มต้นฟิลด์ทั้งหมดผ่าน คอนสตรัคเตอร์ การทำสำเนาลึก
- ดำเนินการ โคลนวัตถุ ในเมธอด getter เพื่อส่งคืนสำเนาแทนที่จะส่งคืนการอ้างอิงอ็อบเจ็กต์จริง
- หากช่องอินสแตนซ์มีการอ้างอิงไปยังวัตถุที่ไม่แน่นอน , ไม่อนุญาตให้วัตถุเหล่านั้นถูกเปลี่ยน
- อย่าให้วิธีการที่ปรับเปลี่ยนไม่แน่นอน วัตถุ .
- อย่าแชร์ข้อมูลอ้างอิง ไปยังวัตถุที่เปลี่ยนแปลงได้ . อย่าเก็บการอ้างอิงถึงวัตถุภายนอกที่เปลี่ยนแปลงได้ซึ่งส่งผ่านไปยังตัวสร้าง หากจำเป็น ให้สร้างสำเนาและจัดเก็บการอ้างอิงถึงสำเนา ในทำนองเดียวกัน ให้สร้างสำเนาของออบเจ็กต์ที่ไม่แน่นอนภายในของเราเมื่อจำเป็น เพื่อหลีกเลี่ยงไม่ให้ส่งคืนต้นฉบับในวิธีการของเรา
ตัวอย่าง
// Employee.java final class Employee { private final String empName; private final int age; private final Address address; public Employee(String name, int age, Address address) { super(); this.empName = name; this.age = age; this.address = address; } public String getEmpName() { return empName; } public int getAge() { return age; } /* public Address getAddress() { return address; } */ public Address getAddress() throws CloneNotSupportedException { return (Address) address.clone(); } } // Address.java class Address implements Cloneable { public String addressType; public String address; public String city; public Address(String addressType, String address, String city) { super(); this.addressType = addressType; this.address = address; this.city = city; } public String getAddressType() { return addressType; } public void setAddressType(String addressType) { this.addressType = addressType; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public Object clone() throws CloneNotSupportedException { return super.clone(); } @Override public String toString() { return "Address Type - "+addressType+", address - "+address+", city - "+city; } } // MainClass.java public class MainClass { public static void main(String[] args) throws Exception { Employee emp = new Employee("Adithya", 34, new Address("Home", "Madhapur", "Hyderabad")); Address address = emp.getAddress(); System.out.println(address); address.setAddress("Hi-tech City"); address.setAddressType("Office"); address.setCity("Hyderabad"); System.out.println(emp.getAddress()); } }
ในตัวอย่างข้างต้น แทนที่จะส่งคืน ที่อยู่ . เดิม วัตถุ เราจะส่งคืน สำเนาโคลนลึก ของกรณีนั้น คลาสที่อยู่ต้องใช้ Cloneable อินเทอร์เฟซ
ผลลัพธ์
Address Type - Home, address - Madhapur, city - Hyderabad Address Type - Home, address - Madhapur, city - Hyderabad