รหัสต่อไปนี้พ่นNullPointerException:
int num = Integer.getInteger("123");
คอมไพเลอร์ของฉันเรียกใช้getIntegernull เนื่องจากเป็นแบบคงที่หรือไม่ นั่นไม่สมเหตุสมผลเลย!
เกิดอะไรขึ้น?
รหัสต่อไปนี้พ่นNullPointerException:
int num = Integer.getInteger("123");
คอมไพเลอร์ของฉันเรียกใช้getIntegernull เนื่องจากเป็นแบบคงที่หรือไม่ นั่นไม่สมเหตุสมผลเลย!
เกิดอะไรขึ้น?
คำตอบ:
มีสองประเด็นในการเล่นที่นี่:
Integer getInteger(String) ไม่ได้ทำในสิ่งที่คุณคิด
nullในกรณีนี้Integerถึงintทำให้เกิดการแกะกล่องอัตโนมัติ
Integerมีnull, NullPointerExceptionโยนที่จะแยก(String) "123"ไปคุณสามารถใช้เช่น(int) 123int Integer.parseInt(String)
Integer การอ้างอิง APIInteger.getIntegerนี่คือสิ่งที่เอกสารได้กล่าวถึงวิธีการนี้:
public static Integer getInteger(String nm): กำหนดค่าจำนวนเต็มของคุณสมบัติระบบด้วยชื่อที่ระบุ หากไม่มีคุณสมบัติที่มีชื่อที่ระบุหากชื่อที่ระบุว่างเปล่าหรือnullหรือหากคุณสมบัติไม่มีรูปแบบตัวเลขที่ถูกต้องระบบnullจะส่งคืน
กล่าวอีกนัยหนึ่งวิธีนี้ไม่มีส่วนเกี่ยวข้องกับการแยกวิเคราะห์ a Stringถึงint/Integerค่า แต่จะเกี่ยวข้องกับSystem.getPropertyวิธีการ
เป็นที่ยอมรับว่าอาจเป็นเรื่องที่น่าประหลาดใจทีเดียว โชคไม่ดีที่ห้องสมุดมีเรื่องน่าประหลาดใจเช่นนี้ แต่มันสอนบทเรียนอันมีค่าให้คุณ: ค้นหาเอกสารเสมอเพื่อยืนยันว่าวิธีการใดทำอย่างไร
โดยบังเอิญความแตกต่างของปัญหานี้ถูกนำเสนอในReturn of the Puzzlers: Schlock and Awe (TS-5186) , Josh Bloch และงานนำเสนอ JavaOne ของ Neal Gafter ในปี 2009 ของ Neal Gafter นี่คือสไลด์สรุป:
คุณธรรม
- วิธีการที่แปลกและน่ากลัวแฝงตัวอยู่ในห้องสมุด
- บางคนมีชื่อที่ฟังดูไม่เป็นอันตราย
- หากรหัสของคุณทำงานผิดปกติ
- ตรวจสอบให้แน่ใจว่าคุณเรียกใช้วิธีการที่ถูกต้อง
- อ่านเอกสารของไลบรารี
- สำหรับนักออกแบบ API
- อย่าละเมิดหลักการของความประหลาดใจอย่างน้อยที่สุด
- อย่าละเมิดลำดับชั้นที่เป็นนามธรรม
- อย่าใช้ชื่อที่คล้ายกันสำหรับพฤติกรรมที่แตกต่างกันอย่างสิ้นเชิง
เพื่อความสมบูรณ์นอกจากนี้ยังมีวิธีการเหล่านี้ที่คล้ายคลึงกับInteger.getInteger:
แน่นอนปัญหาอื่น ๆ คือวิธีการNullPointerExceptionโยน เพื่อมุ่งเน้นไปที่ปัญหานี้เราสามารถลดความซับซ้อนของข้อมูลโค้ดได้ดังนี้:
Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!
นี่คือคำพูดจาก Effective Java 2nd Edition, Item 49: ชอบประเภทดั้งเดิมกับ primitives แบบบรรจุกล่อง:
โดยสรุปให้ใช้ primitives ตามความต้องการของ primitive แบบกล่องเมื่อใดก็ตามที่คุณมีทางเลือก ประเภทดั้งเดิมนั้นง่ายกว่าและเร็วกว่า หากคุณต้องใช้ผลิตภัณฑ์ดั้งเดิมชนิดบรรจุกล่องโปรดระวัง! Autoboxing ช่วยลดความฟุ่มเฟือย แต่ไม่เป็นอันตรายจากการใช้แบบดั้งเดิมชนิดบรรจุกล่อง เมื่อโปรแกรมของคุณเปรียบเทียบแบบดั้งเดิมสองกล่องกับตัว
==ดำเนินการจะทำการเปรียบเทียบตัวตนซึ่งแทบจะไม่ใช่สิ่งที่คุณต้องการ เมื่อโปรแกรมของคุณทำการคำนวณแบบผสมที่เกี่ยวข้องกับไพรเมทีฟชนิดบรรจุกล่องและแบบไม่มีกล่องโปรแกรมจะทำการแกะกล่องและเมื่อโปรแกรมของคุณทำการแกะกล่องก็สามารถโยนNullPointerExceptionได้ สุดท้ายเมื่อโปรแกรมของคุณใส่ค่าดั้งเดิมอาจส่งผลให้เกิดการสร้างวัตถุที่มีราคาแพงและไม่จำเป็น
มีหลายสถานที่ที่คุณไม่มีทางเลือกอื่นนอกจากการใช้ยาดั้งเดิมชนิดบรรจุกล่องเช่นยาชื่อสามัญ แต่อย่างอื่นคุณควรพิจารณาอย่างจริงจังว่าการตัดสินใจใช้ยาดั้งเดิมชนิดบรรจุกล่องนั้นสมเหตุสมผลหรือไม่
Integer.getInteger(s)เทียบเท่ากับInteger.parseInt(System.getProperty(s))? ฉันคิดว่าฉันชอบอันที่สองแม้ว่ามันจะละเอียดกว่าเพราะมันเน้นความจริงที่ว่าคุณกำลังดึงข้อมูลจากคุณสมบัติของระบบ
Integer.decodeแทนInteger.parseIntซึ่งมองหาเลขนำหน้า0xหรือ0เพื่อแยกวิเคราะห์ตัวเลขเป็นเลขฐานสิบหกหรือฐานแปดตามลำดับ
NullPointerException? : programmers.stackexchange.com/questions/158908/…
จากhttp://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html :
getInteger 'กำหนดค่าจำนวนเต็มของคุณสมบัติระบบด้วยชื่อที่ระบุ'
คุณต้องการสิ่งนี้:
Integer.parseInt("123")
กรุณาตรวจสอบเอกสารของวิธีการgetInteger () ในวิธีนี้Stringพารามิเตอร์คือคุณสมบัติของระบบที่กำหนดค่าจำนวนเต็มของคุณสมบัติระบบด้วยชื่อที่ระบุ "123" ไม่ได้เป็นชื่อของสถานที่ให้บริการระบบใด ๆ ตามที่กล่าวไว้ที่นี่ หากคุณต้องการแปลงสตริงนี้ให้intใช้วิธีการเป็น
int num = Integer.parseInt("123").