ตัวดำเนินการ Ternary ใน Java ประเมินเพียงนิพจน์เดียวตั้งแต่ Java 7 - Java 1.6 และต่ำกว่านั้นแตกต่างกันหรือไม่


109

การเตรียมตัวสำหรับการสอบ Oracle Certified Associate Java SE 8 Programmer 1 ฉันพบย่อหน้าต่อไปนี้เกี่ยวกับนิพจน์ด้านท้ายในคู่มือการศึกษาอย่างเป็นทางการ:

การประเมินนิพจน์ Ternary
ณ Java 7 นิพจน์ทางขวามือเดียวของตัวดำเนินการ ternary จะได้รับการประเมินที่รันไทม์ ในลักษณะที่คล้ายกับตัวดำเนินการลัดวงจรหากหนึ่งในสองนิพจน์ขวามือในตัวดำเนินการที่เกี่ยวข้องมีผลข้างเคียงก็อาจไม่สามารถใช้ในรันไทม์ได้ ขอยกตัวอย่างหลักการนี้ด้วยตัวอย่างต่อไปนี้: [... ]

มันบอกว่ามีการประเมินเพียงหนึ่งในสองนิพจน์โดยแสดงให้เห็นด้วยตัวอย่างต่อไปนี้:

int y = 1;
int z = 1;
int a = y < 10 ? y++ : z++;

ที่นี่yเพิ่มขึ้นเท่านั้นแต่zไม่เป็นไปตามที่คุณคาดหวัง

สิ่งที่ฉันสะดุดคือจุดเริ่มต้นของย่อหน้า (ทำเครื่องหมายด้วยสีเหลือง) ซึ่งมีข้อความว่า "As of Java 7, ... " ฉันทดสอบโค้ดเดียวกันกับ Java 1.6 และไม่พบความแตกต่างในลักษณะการทำงาน ฉันคาดว่า Java 1.6 จะประเมินนิพจน์ทั้งสองจากข้อมูลที่ระบุในย่อหน้า ใครมีความคิดที่อยากจะพูดกับ "As of Java 7, ... " บ้าง?

แก้ไข:เพื่อหลีกเลี่ยงความสับสน: คำถามนี้ทำให้เกิดคำถามเนื่องจากพวกเขาเขียนว่า 'As of Java 7' มีอะไรเปลี่ยนแปลงเกี่ยวกับตัวดำเนินการ ternary เมื่อเปลี่ยนจาก Java 6 เป็น Java 7 หรือไม่?


4
ทำไมคุณถึงคาดหวังว่า z จะเพิ่มขึ้นด้วย? นี่ไม่สมเหตุสมผลกับฉันเลย
Jiří Kantor

15
ดูเหมือนเป็นหนังสือที่เขียนไม่ดีตัวดำเนินการสามส่วนไม่ได้เปลี่ยนไปเลยนับตั้งแต่มีการสร้าง java, afaik
NimChimpsky

23
เมื่ออ่านคำตอบส่วนใหญ่ที่โพสต์แล้วดูเหมือนว่าผู้คนจะตีความคำถามผิดไป ไม่ใช่ "เหตุใดทั้งสองสำนวนจึงไม่ได้รับการประเมิน" แต่เป็น "ทำไมหนังสือเล่มนี้จึงมีนัยว่าหนังสือเล่มนี้เคยมีพฤติกรรมแตกต่างกัน"
BambooleanLogic

23
ที่จริงฉันเคยเห็น "ณ วันที่ / เวอร์ชัน X" เคยหมายถึง "เราตรวจสอบแล้วว่าเป็นจริงในวันที่ / ในเวอร์ชัน X แต่เราไม่ได้พูดอะไรเกี่ยวกับเวอร์ชันก่อนหน้านี้" ฉันเดาว่านั่นอาจเป็นความหมายที่นี่ (แม้ว่าคุณจะคิดว่ามันง่ายพอที่จะตรวจสอบ Java เวอร์ชันก่อนหน้านี้) อย่างไรก็ตามนั่นเป็นปัญหาภาษาอังกฤษมากกว่าการเขียนโปรแกรม
David Z

14
@DavidZ: ปัญหาภาษาอังกฤษเป็นปัญหาการเขียนโปรแกรมเมื่อพวกเขาหยุดคุณจากการทำงานให้เสร็จ ความคิดเห็นที่ไม่ดีนี้ทำให้ OP หยุดสิ่งที่เขากำลังทำและเสียเวลาไปกับการค้นพบว่าไม่มีอะไรเปลี่ยนแปลง การเขียนโปรแกรมคือการสื่อสารไปยังคอมไพเลอร์ / ล่ามและใครก็ตามที่เข้ามาในภายหลังเพื่อรักษารหัสของคุณ ฉันไม่สามารถนับจำนวนครั้งที่ฉันอ่านโค้ดได้และต้องหยุดเพราะมีบางอย่างแปลก ๆ ที่ / อาจ / มีส่วนเกี่ยวข้องกับปัญหาเพียงเพื่อจะพบว่ามัน "วลี" ไม่ดี
jmoreno

คำตอบ:


92

ฉันเป็นหนึ่งในผู้เขียนหนังสือเล่มนี้มาจาก แม้ว่าฉันจะไม่ได้เขียนประโยคนั้น แต่ฉันยอมรับว่าเจตนาคือ "สิ่งนี้ถูกทดสอบบน Java 7" ฉันจะจดบันทึกเพื่อลบออกหากเราเขียนฉบับอื่น

เพื่อความชัดเจนตัวดำเนินการ ternary ทำงานในลักษณะเดียวกันใน Java 8, 7, 6 และอื่น ๆ และฉันจะค่อนข้างแปลกใจหากมีการเปลี่ยนแปลงในอนาคต


116

จากJava 6 JLS :

ในขณะรันนิพจน์ตัวถูกดำเนินการแรกของนิพจน์เงื่อนไขจะถูกประเมินก่อน หากจำเป็นการแปลงแบบ unboxing จะดำเนินการกับผลลัพธ์ จากนั้นค่าบูลีนที่เป็นผลลัพธ์จะถูกใช้เพื่อเลือกนิพจน์ตัวถูกดำเนินการที่สองหรือที่สาม:

  • ถ้าค่าของตัวถูกดำเนินการแรกเป็นจริงนิพจน์ตัวถูกดำเนินการที่สองจะถูกเลือก
  • หากค่าของตัวถูกดำเนินการตัวแรกเป็นเท็จนิพจน์ตัวถูกดำเนินการที่สามจะถูกเลือก

จากนั้นนิพจน์ตัวถูกดำเนินการที่เลือกจะได้รับการประเมินและค่าผลลัพธ์จะถูกแปลงเป็นชนิดของนิพจน์เงื่อนไขตามที่กำหนดโดยกฎที่ระบุไว้ข้างต้น การแปลงนี้อาจรวมถึงมวย (§5.1.7) หรือการแปลงแบบแกะกล่อง นิพจน์ตัวถูกดำเนินการที่ไม่ได้เลือกจะไม่ได้รับการประเมินสำหรับการประเมินนิพจน์เงื่อนไขนั้นโดยเฉพาะ

ถ้อยคำที่คล้ายกันนอกจากนี้ยังปรากฏในรุ่น JLS จะกลับไปที่1.0 พฤติกรรมไม่เปลี่ยนแปลงใน Java 7; คู่มือการศึกษานั้นใช้คำไม่ดี


2
ดังนั้นคำตอบคือ "ไม่มีความแตกต่างเหมือนกับ Java 7 และก่อนหน้าเกี่ยวกับตัวดำเนินการ ternary" ใช่ไหม?
Mathias Bader

5
ดูเหมือนว่าเชื่อถือได้. ฉันเขียนบันทึกถึงผู้เขียน - รอคอยคำตอบ
Mathias Bader

คุณอาจพบ URL ที่เปรียบเทียบรหัสของตัวดำเนินการระหว่างเวอร์ชัน หากคุณหวาดระแวง / อยากรู้อยากเห็น
Steve Clay

7
จำนวนคำถามที่เขียนไม่ดี (หรือเพียงแค่แบนผิด) ในใบรับรอง Oracle เหล่านี้น่าประหลาดใจทุกครั้งอีกครั้ง ..
Voo
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.