NullPointerException ในนิพจน์แบบไตรภาคที่มีค่า null Long

เหตุใดบรรทัดโค้ดต่อไปนี้จึงสร้าง NullPointerException

Long v = 1 == 2 ? Long.MAX_VALUE : (Long) null;

ฉันเข้าใจว่ากำลังทำการแกะกล่องในวันที่ null แต่ทำไม

โปรดทราบว่า

Long v = (Long) null;

ไม่ก่อให้เกิดข้อยกเว้น


person jonderry    schedule 15.12.2011    source แหล่งที่มา
comment
คุณทำ a v=((1==2)?Long.MAX_VALUE : (Long) null); นี่เป็นเท็จเสมอ ดังนั้นคุณจึงพยายามแปลงค่าว่างเป็นค่า Long เสมอ ดูเหมือนว่าจะไม่ได้รับอนุญาตและทำให้เกิดข้อยกเว้นของคุณ   -  person evildead    schedule 15.12.2011
comment
ทำไมคุณถึงมีบรรทัดของรหัสเช่นนี้? ความอยากรู้อยากเห็นทางปัญญาหรือเป็นเพียงตัวอย่างจากรหัสการผลิตจริง?   -  person Paul    schedule 15.12.2011
comment
@Paul และ evildead ดูเหมือนโค้ดตัวอย่างเพื่อแสดงลำดับการแกะกล่อง   -  person Steven    schedule 15.12.2011
comment
มีทุกอย่างที่เกี่ยวข้องกับ java.sun.com/ docs/books/jls/third_edition/html/   -  person Steven    schedule 15.12.2011
comment
@Paul นี่มาจากการผลิต แต่ทำให้ง่ายขึ้นเพื่อสร้างข้อยกเว้นในโค้ดง่ายๆ   -  person jonderry    schedule 15.12.2011
comment
ทำไมคุณไม่แยกตัวดำเนินการที่ประกอบไปด้วย if/then/else ออกล่ะ? นั่นอาจช่วยให้คุณไขปริศนานี้ได้   -  person Paul    schedule 15.12.2011
comment
มาจากการผลิตเหรอ? เป็นอีกครั้งที่ความสามารถในการอ่านมีชัยเหนือความฉลาด...   -  person Paul    schedule 15.12.2011
comment
@Paul หากคุณแยกออกเป็น if/then/else ปัญหาจะหายไป   -  person Tom Hawtin - tackline    schedule 15.12.2011
comment
แบ่งเป็นถ้าอย่างอื่นทำให้ข้อยกเว้นหายไป ฉันแค่สงสัยว่าทำไมไวยากรณ์แบบไตรภาคทำให้เกิดข้อยกเว้นนี้   -  person jonderry    schedule 15.12.2011
comment
ที่เกี่ยวข้อง: stackoverflow.com/questions/3882095/ วิธีแก้ไขคือย้ายนักแสดงนั้นไปที่ Long.MAX_VALUE ของคุณเมื่อส่งคืน long   -  person BalusC    schedule 15.12.2011
comment
@ทอม พวกเขาควรลบอินสแตนซ์ดังกล่าวทั้งหมดออกจากโค้ด ทำให้คนที่เขียนพวกเขาซื้อโดนัทให้กับทีม จากนั้นอ่านตามลำดับความสำคัญ   -  person Paul    schedule 15.12.2011


คำตอบ (2)


ดังนั้นจึงดูชัดเจนว่าคุณจะต้องใส่กล่องเมื่อเงื่อนไขเป็นจริงเท่านั้น และไม่ควรมีการใส่กล่องหากเงื่อนไขเป็นเท็จ อย่างไรก็ตาม นิพจน์ตัวดำเนินการแบบไตรภาคจะต้องมีประเภท คงที่ โดยเฉพาะ ดังนั้นเราจึงมี Long และ long JLS ระบุว่าผลลัพธ์จะเป็นแบบดั้งเดิม (เช่นกัน - ลองจินตนาการว่าตัวดำเนินการคือ + หรือแม้แต่ ==) ดังนั้นผู้ดำเนินการที่ประกอบไปด้วยจะบังคับแกะกล่อง และจากนั้นการมอบหมายงานจะทำให้เกิดการชกมวยเท่านั้น

หากคุณต้องแทนที่โค้ดด้วย if-else ที่เทียบเท่า คุณก็จะมีการกำหนดจาก long ถึง Long และจาก Long ถึง Long ซึ่งจะไม่มีการแกะกล่องใดๆ และทำงานได้ดี

IIRC สิ่งนี้ครอบคลุมถึง Java Puzzlers ของ Bloch & Gafter

person Tom Hawtin - tackline    schedule 15.12.2011

จาก JSL

  1. หากตัวถูกดำเนินการตัวที่สองและสามมีประเภทเดียวกัน (ซึ่งอาจเป็นประเภทว่าง) นั่นคือประเภทของนิพจน์เงื่อนไข
  2. หากตัวถูกดำเนินการตัวที่สองและสามตัวใดตัวหนึ่งเป็นประเภท boolean และอีกตัวเป็นประเภท Boolean ดังนั้นประเภทของนิพจน์เงื่อนไขจะเป็น boolean

ในคำสั่งต่อไปนี้ ประเภทของตัวถูกดำเนินการตัวที่สองคือ long และตัวที่สามคือ Long

Long v = 1 == 2 ? Long.MAX_VALUE :  (Long) null;

วิธีนี้จะได้ผลหากนิพจน์เป็นจริง

Long v= 1 == 1 ?  Long.MAX_VALUE : (Long) null;

หรือคุณจะโยนมันก็ได้

Long v= 1 == 2 ?  Long.valueOf(Long.MAX_VALUE) : (Long) null;
person kv-prajapati    schedule 15.12.2011
comment
ใช่ ฉันรู้ว่ามันกำลังทำการแกะกล่อง และคุณไม่สามารถแกะกล่องค่าว่างได้ ฉันถามว่าทำไมถึงพยายามทำการแกะกล่องในกรณีนี้ - person jonderry; 15.12.2011
comment
นั่นไม่ถูกต้องทั้งหมด เขากำลังพยายามแกะกล่องวัตถุ Long ที่เป็นโมฆะ นักแสดงไม่ใช่ปัญหา คุณสามารถส่ง null ไปยังวัตถุประเภทใดก็ได้ โปรดดูข้อมูลจำเพาะภาษา Java ส่วนที่ 5.5 ใต้หากการส่งไปยังประเภทการอ้างอิงไม่ใช่ข้อผิดพลาดเวลาคอมไพล์ มีหลายกรณี: - person Paul; 15.12.2011