เทคนิคการโยนสามารถทำได้ ไม่สามารถพิสูจน์ได้อย่างง่ายดายโดย javac ว่าไม่ใช่ในกรณีของคุณและ JLS กำหนดว่านี่เป็นโปรแกรม Java ที่ถูกต้องดังนั้นการตั้งค่าสถานะข้อผิดพลาดจะไม่ถูกต้อง
นี่เป็นเพราะList
เป็นอินเทอร์เฟซ ดังนั้นคุณอาจมีคลาสย่อยของDate
ที่ใช้จริงList
ปลอมตัวเป็นList
ที่นี่ - แล้วหล่อมันDate
จะตกลงอย่างสมบูรณ์ ตัวอย่างเช่น:
public class SneakyListDate extends Date implements List<Foo> {
...
}
แล้ว:
List<Foo> list = new SneakyListDate();
Date date = (Date) list; // This one is valid, compiles and runs just fine
การตรวจจับสถานการณ์ดังกล่าวอาจไม่สามารถทำได้เสมอไปเนื่องจากต้องใช้ข้อมูลรันไทม์หากอินสแตนซ์นั้นมาจากตัวอย่างเช่นเมธอดแทน และถึงแม้ว่ามันจะต้องใช้ความพยายามมากขึ้นสำหรับคอมไพเลอร์ คอมไพเลอร์ป้องกันการปลดเปลื้องที่เป็นไปไม่ได้อย่างแน่นอนเนื่องจากไม่มีวิธีใดที่ทรีคลาสจะจับคู่ได้เลย ซึ่งไม่ใช่กรณีที่นี่ตามที่เห็น
โปรดทราบว่า JLS ต้องการให้รหัสของคุณเป็นโปรแกรม Java ที่ถูกต้อง ใน5.1.6.1 การแปลงอ้างอิงที่อนุญาตให้แคบลงนั้นระบุว่า:
การแปลงอ้างอิงกวดขันอยู่จากชนิดอ้างอิงS
กับประเภทอ้างอิงT
ถ้าทั้งหมดต่อไปนี้เป็นจริง :
- [ ... ]
- กรณีใดกรณีหนึ่งต่อไปนี้ :
- [ ... ]
S
เป็นประเภทอินเตอร์เฟสT
เป็นประเภทคลาสและT
ไม่ตั้งชื่อfinal
คลาส
ดังนั้นแม้ว่าคอมไพเลอร์สามารถเข้าใจว่ากรณีของคุณเป็นไปไม่ได้จริง ๆ แล้วมันไม่ได้รับอนุญาตให้ตั้งค่าสถานะข้อผิดพลาดเพราะ JLS กำหนดว่าเป็นโปรแกรม Java ที่ถูกต้อง
มันจะได้รับอนุญาตเท่านั้นที่จะแสดงคำเตือน
List
ที่นี่Date d = (Date) new Object();