การใช้requireNonNull()
เป็นคำสั่งแรกในวิธีการอนุญาตให้ระบุได้ทันที / รวดเร็วสาเหตุของข้อยกเว้น
stacktrace บ่งชี้อย่างชัดเจนว่ามีการโยนข้อยกเว้นทันทีที่รายการของวิธีการเนื่องจากผู้โทรไม่เคารพข้อกำหนด / สัญญา
การส่งnull
วัตถุไปยังวิธีอื่นอาจกระตุ้นให้เกิดข้อยกเว้นในแต่ละครั้ง แต่สาเหตุของปัญหาอาจซับซ้อนกว่าที่จะเข้าใจเนื่องจากข้อยกเว้นจะถูกส่งออกไปในการร้องขอเฉพาะบนnull
วัตถุที่อาจเพิ่มขึ้นอีกมาก
นี่คือรูปธรรมและเป็นจริงตัวอย่างที่แสดงให้เห็นว่าทำไมเรามีเพื่อให้ประโยชน์แก่ล้มเหลวอย่างรวดเร็วโดยทั่วไปและอื่น ๆ โดยเฉพาะอย่างยิ่งการใช้Object.requireNonNull()
หรือวิธีการใด ๆ ที่จะดำเนินการตรวจสอบไม่มี null null
พารามิเตอร์ที่ออกแบบมาให้ไม่ได้
สมมติว่าDictionary
คลาสที่ประกอบด้วย a LookupService
และ a List
ของString
คำที่มีอยู่ในฟิลด์เหล่านี้ถูกออกแบบมาให้ไม่null
และหนึ่งในนั้นจะถูกส่งผ่านในตัว Dictionary
สร้าง
ทีนี้สมมติว่าการใช้งาน "ไม่ดี" Dictionary
โดยไม่มีการnull
ตรวจสอบในรายการวิธีการ (นี่คือตัวสร้าง)
public class Dictionary {
private final List<String> words;
private final LookupService lookupService;
public Dictionary(List<String> words) {
this.words = this.words;
this.lookupService = new LookupService(words);
}
public boolean isFirstElement(String userData) {
return lookupService.isFirstElement(userData);
}
}
public class LookupService {
List<String> words;
public LookupService(List<String> words) {
this.words = words;
}
public boolean isFirstElement(String userData) {
return words.get(0).contains(userData);
}
}
ตอนนี้ลองเรียกใช้ตัวDictionary
สร้างพร้อมการnull
อ้างอิงwords
พารามิเตอร์:
Dictionary dictionary = new Dictionary(null);
// exception thrown lately : only in the next statement
boolean isFirstElement = dictionary.isFirstElement("anyThing");
JVM จะพ่น NPE ที่คำสั่งนี้
return words.get(0).contains(userData);
ข้อยกเว้นในเธรด "main" java.lang.NullPointerException
ที่ LookupService.isFirstElement (LookupService.java,5)
ที่ Dictionary.isFirstElement (Dictionary.java:15)
ที่ Dictionary.main (Dictionary.java:22)
ข้อยกเว้นจะเกิดขึ้นในLookupService
ชั้นเรียนในขณะที่ต้นกำเนิดของมันเป็นอย่างดีก่อนหน้านี้ ( Dictionary
นวกรรมิก) มันทำให้การวิเคราะห์ปัญหาโดยรวมชัดเจนน้อยลง
คือwords
null
อะไร คือwords.get(0) null
อะไร ทั้งคู่ ทำไมคนอื่น ๆ หรืออาจจะทั้งสองnull
? มันเป็นข้อผิดพลาดในการเขียนในDictionary
(นวกรรมิก? วิธีการเรียก?)? มันเป็นข้อผิดพลาดในการเขียนโปรแกรมLookupService
หรือไม่? (วิธีการเรียกใช้ตัวสร้าง?)?
ในที่สุดเราจะต้องตรวจสอบรหัสเพิ่มเติมเพื่อค้นหาต้นกำเนิดข้อผิดพลาดและในชั้นเรียนที่ซับซ้อนยิ่งขึ้นอาจใช้ตัวดีบักเพื่อทำความเข้าใจได้ง่ายขึ้นว่าเกิดอะไรขึ้น
แต่ทำไมเรื่องง่าย ๆ (การขาดเช็คว่าง) กลายเป็นปัญหาที่ซับซ้อน?
เนื่องจากเราอนุญาตให้ข้อผิดพลาดเริ่มต้น / การขาดหายไปที่ระบุในการรั่วไหลของส่วนประกอบเฉพาะในส่วนประกอบที่ต่ำกว่า
ลองนึกภาพที่LookupService
ไม่ได้เป็นบริการในท้องถิ่น แต่เป็นบริการระยะไกลหรือห้องสมุดของบุคคลที่สามที่มีข้อมูลการแก้ไขข้อบกพร่องเล็กน้อยหรือจินตนาการว่าคุณไม่มี 2 ชั้น แต่มีการเรียกใช้วัตถุ 4 หรือ 5 ชั้นก่อนที่null
จะถูกตรวจพบ ปัญหาจะยังคงซับซ้อนในการวิเคราะห์
ดังนั้นวิธีที่จะชอบคือ:
public Dictionary(List<String> words) {
this.words = Objects.requireNonNull(words);
this.lookupService = new LookupService(words);
}
ด้วยวิธีนี้ไม่มีอาการปวดหัว: เราได้รับข้อผิดพลาดทันทีที่ได้รับ:
// exception thrown early : in the constructor
Dictionary dictionary = new Dictionary(null);
// we never arrive here
boolean isFirstElement = dictionary.isFirstElement("anyThing");
ข้อยกเว้นในเธรด "main" java.lang.NullPointerException
ที่ java.util.Objects.requireNonNull (Objects.java:203)
ที่ com.Dictionary. (Dictionary.java:15)
at com.Dictionary.main (Dictionary.java:24)
โปรดทราบว่าที่นี่ฉันแสดงให้เห็นปัญหากับนวกรรมิก แต่การเรียกใช้เมธอดอาจมีข้อ จำกัด การตรวจสอบที่ไม่ใช่ค่า null เดียวกัน