ฉันเห็น POJO ที่ไม่เปลี่ยนรูปที่สุดเขียนแบบนี้:
public class MyObject {
private final String foo;
private final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public int getBar() {
return bar;
}
}
แต่ฉันมักจะเขียนแบบนี้:
public class MyObject {
public final String foo;
public final int bar;
public MyObject(String foo, int bar) {
this.foo = foo;
this.bar = bar;
}
}
โปรดสังเกตว่าการอ้างอิงนั้นเป็นที่สิ้นสุดดังนั้น Object ยังคงไม่เปลี่ยนรูป มันช่วยให้ฉันเขียนโค้ดน้อยลงและอนุญาตการเข้าถึงที่สั้นลง (5 ตัวอักษร: get
และ()
)
ข้อเสียเดียวที่ฉันเห็นคือถ้าคุณต้องการเปลี่ยนการใช้งานของgetFoo()
ถนนเพื่อทำสิ่งที่บ้าคุณไม่สามารถ แต่ในความเป็นจริงสิ่งนี้ไม่เคยเกิดขึ้นเพราะวัตถุนั้นไม่เปลี่ยนรูป คุณสามารถตรวจสอบในระหว่างการเริ่มต้นสร้างสำเนาการป้องกันที่ไม่เปลี่ยนรูปแบบในระหว่างการเริ่มต้น (ดูImmutableList
ตัวอย่างของ Guava ) และทำให้วัตถุfoo
หรือbar
พร้อมสำหรับการget
โทร
มีข้อเสียใด ๆ ที่ฉันหายไปหรือไม่?
แก้ไข
ฉันคิดว่าข้อเสียอีกอย่างที่ฉันขาดไปคือไลบรารี่อนุกรมที่ใช้การสะท้อนวิธีการที่ขึ้นต้นด้วยget
หรือis
นั่นเป็นวิธีปฏิบัติที่แย่มาก ...
String
, หรือint
MyObject
ในรุ่นแรกfinal
เป็นเพียงเพื่อให้แน่ใจว่าวิธีการอื่น ๆ กว่าสร้างภายในชั้นเรียนไม่พยายามที่จะbar = 7;
ยกตัวอย่างเช่น ในรุ่นที่สองเป็นสิ่งที่จำเป็นเพื่อป้องกันไม่ให้ผู้บริโภคจากการทำ:final
MyObject x = new MyObject("hi", 5); x.bar = 7;
Object
ของคุณถือเป็นที่สิ้นสุดดังนั้นสิ่งที่ยังไม่เปลี่ยนรูปแบบ " ก็คือการทำให้เข้าใจผิด - ด้วยวิธีนี้ดูเหมือนว่าคุณคิดว่าสิ่งใดfinal Object
เป็นสิ่งที่ไม่เปลี่ยนรูปซึ่งไม่ได้เป็นเช่นนั้น ขอโทษที่เข้าใจผิด.
myObj.getFoo().setFrob(...)
-
final
ไม่ทำให้ตัวแปรเป็นวัตถุที่ไม่เปลี่ยนรูป ปกติฉันจะใช้การออกแบบที่ฉันกำหนดfinal
เขตข้อมูลก่อนที่จะสร้างการโทรกลับเพื่อให้การเรียกกลับสามารถเข้าถึงเขตข้อมูลเหล่านั้น แน่นอนสามารถเรียกใช้วิธีการทั้งหมดรวมถึงsetX
วิธีการใดก็ได้