วัตถุที่ไม่เปลี่ยนรูป คืออ็อบเจ็กต์ที่สถานะ ไม่สามารถเปลี่ยนแปลงได้เมื่อเริ่มต้น . บางครั้งจำเป็นต้องสร้างคลาสที่ไม่เปลี่ยนรูปตามความต้องการ ตัวอย่างเช่น คลาส 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