Java Collections.checkedList: กันชน type ตอนรับ List จาก legacy boundary
Generics ช่วยตอน compile แต่เมื่อระบบต้องเชื่อม raw collection จาก legacy code, reflection หรือ plugin การปน type อาจระเบิดไกลจากต้นเหตุครับ Collections.checkedList(list, Type.class) คืน view ที่ตรวจ element ใหม่ตอนเขียนและโยน ClassCastException ตรง boundary
WHY: ตรวจของตรงประตูโกดัง
เหมือนช่องรับของที่ยอมเฉพาะกล่องรูปทรงหนึ่ง ปัญหาถูกจับตอนนำเข้า ไม่ใช่ตอนพนักงานอีกแผนกเปิดกล่องหลายชั่วโมงต่อมา แต่ประตูนี้ตรวจเฉพาะของที่ผ่าน view ถ้ามีประตูหลังหรือของผิดอยู่ในโกดังเดิม มันไม่ย้อนซ่อมให้
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
@SuppressWarnings({"rawtypes", "unchecked"})
public static void main(String[] args) {
List raw = new ArrayList();
List<String> names = Collections.checkedList(raw, String.class);
names.add("forest");
assert names.equals(List.of("forest"));
boolean rejected = false;
try {
((List) names).add(42);
} catch (ClassCastException expected) {
rejected = true;
}
assert rejected;
raw.add(0, 99);
boolean latentBadValue = false;
try {
String ignored = names.get(0);
} catch (ClassCastException expected) {
latentBadValue = true;
}
assert latentBadValue;
}
}
View ต้องเป็นทางเข้าหลักจริง
ถ้าเก็บ raw alias ไว้ คนอื่นยังเขียนค่าผิดเข้าคอลเล็กชันเดิมได้ จึงควรซ่อน backing list และส่งเฉพาะ checked view ออกจาก adapter ส่วนข้อมูลที่มีอยู่แล้วต้อง scan/convert ตอนรับเข้าระบบ
การตรวจ class ไม่ตรวจ semantic เช่น string ว่าง, path traversal หรือ ID ผิดรูปแบบ ต้องมี validation ของโดเมนอีกชั้น และอย่าใช้ raw type ในโค้ดใหม่เพื่อจำลองปัญหาโดยไม่จำเป็น
Recap
- ใช้ checked view ตรง legacy/plugin boundary
- ปิด raw alias ไม่ให้เป็นประตูหลัง
- validate ข้อมูลเดิมก่อนรับ ownership
- แยก runtime type check จาก domain validation