ไม่มีใครชอบ NullPointerException! มีวิธีใดบ้างที่จะหลีกเลี่ยงพวกเขา? อาจจะ. -
บทความนี้จะกล่าวถึงเทคโนโลยีดังต่อไปนี้
1.ประเภทเสริม (เปิดตัวใหม่ใน Java 8)
2.คลาสอ็อบเจ็กต์ (ต้นฉบับใน Java 7)
คลาสเสริมใน Java 8
มันคืออะไร?
1. ประเภทใหม่ที่นำมาใช้ใน Java 8
2. มันถูกใช้เป็น wrapper สำหรับวัตถุประเภทที่ระบุหรือสำหรับสถานการณ์ที่ไม่มีวัตถุ (null) อยู่
พูดง่ายๆ ก็คือเป็นทางเลือกที่ดีกว่าสำหรับการจัดการค่า Null (คำเตือน: อาจไม่ชัดเจนนักเมื่อมองแวบแรก)
การใช้งานขั้นพื้นฐาน
มันเป็นประเภท (คลาส) - แล้วคุณจะสร้างอินสแตนซ์ประเภทนี้ได้อย่างไร?
เพียงใช้วิธีการคงที่สามวิธี:
คัดลอกรหัสรหัสดังต่อไปนี้:
สาธารณะแบบคงที่ตัวเลือก <String> stringOptional (อินพุตสตริง) {
กลับตัวเลือกของ (อินพุต);
-
เรียบง่ายและชัดเจน - สร้างกระดาษห่อเสริมที่มีค่านี้ ข้อควรจำ - หากค่านี้เป็นโมฆะ ระบบจะโยน NPE!
คัดลอกรหัสรหัสดังต่อไปนี้:
สาธารณะแบบคงที่ตัวเลือก <String> stringNullableOptional (อินพุตสตริง) {
ถ้า (!สุ่มใหม่().nextBoolean()) {
อินพุต = โมฆะ;
-
กลับ Optional.ofNullable (อินพุต);
-
ส่วนตัวผมคิดว่าดีกว่าครับ วิธีนี้จะไม่มีความเสี่ยงต่อ NPE - หากอินพุตเป็นโมฆะ ระบบจะส่งคืนตัวเลือกว่าง
คัดลอกรหัสรหัสดังต่อไปนี้:
สาธารณะแบบคงที่ตัวเลือก <String> EmptyOptional() {
กลับตัวเลือก.empty();
-
หากคุณต้องการส่งกลับค่า "null" จริงๆ ค่า "ว่าง" ไม่ได้หมายความว่าเป็นโมฆะ
เอาล่ะ แล้วจะบริโภค/ใช้ Optional อย่างไร?
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะคงที่สาธารณะ การบริโภคตัวเลือก () {
ตัวเลือก<String> ห่อ = Optional.of("aString");
ถ้า (wrapped.isPresent()) {
System.out.println("มีสตริง - " + wrap.get());
-
อื่น {
System.out.println("Gotcha !");
-
-
วิธีง่ายๆ คือการตรวจสอบว่า wrapper เสริมมีค่าจริงหรือไม่ (โดยใช้เมธอด isPresent) คุณจะสงสัยว่าสิ่งนี้มีข้อดีมากกว่าการใช้ if(myObj != null) อย่างไร ไม่ต้องกังวล ฉันจะอธิบายเรื่องนี้ให้ชัดเจน
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะคงที่สาธารณะ บริโภคNullableOptional() {
อินพุตสตริง = null;
ถ้า (สุ่มใหม่ ().nextBoolean()) {
อินพุต = "iCanBeNull";
-
ตัวเลือก <String> ห่อ = Optional.ofNullable (อินพุต);
System.out.println(wrapped.orElse("ค่าเริ่มต้น"));
-
คุณสามารถใช้เมธอด orElse ได้ เพื่อว่าถ้าค่าที่ห่อหุ้มเป็นค่าว่างจริงๆ คุณสามารถใช้เมธอดนี้เพื่อส่งกลับค่าเริ่มต้นได้ ซึ่งประโยชน์ของวิธีนี้จะเห็นได้ชัด เมื่อดึงค่าจริงออกมา คุณสามารถหลีกเลี่ยงวิธีการเรียกเมธอด ifPresent ที่ซ้ำซ้อนอย่างเห็นได้ชัด
คัดลอกรหัสรหัสดังต่อไปนี้:
โมฆะคงที่สาธารณะ บริโภคEmptyOptional () {
อินพุตสตริง = null;
ถ้า (สุ่มใหม่ ().nextBoolean()) {
อินพุต = "iCanBeNull";
-
ตัวเลือก <String> ห่อ = Optional.ofNullable (อินพุต);
System.out.println (ห่อหรือ ElseGet (
-
กลับ "defaultBySupplier";
-
-
-
ฉันสับสนเล็กน้อยเกี่ยวกับเรื่องนี้ เหตุใดจึงมีสองวิธีที่แตกต่างกันเพื่อจุดประสงค์เดียวกัน orElse และ orElseGet สามารถโอเวอร์โหลดได้อย่างเห็นได้ชัด (ด้วยชื่อเดียวกัน แต่มีพารามิเตอร์ต่างกัน)
อย่างไรก็ตาม ความแตกต่างที่ชัดเจนระหว่างสองวิธีนี้คือพารามิเตอร์ - คุณสามารถเลือกใช้แลมบ์ดานิพจน์แทนอินสแตนซ์ของ Supplier เพื่อทำสิ่งนี้ให้สำเร็จ (อินเทอร์เฟซการทำงาน)
เหตุใดการใช้ตัวเลือกจึงดีกว่าการตรวจสอบค่าว่างทั่วไป
1. ข้อได้เปรียบที่ใหญ่ที่สุดของการใช้ Optional คือคุณสามารถแสดงความตั้งใจของคุณได้ชัดเจนยิ่งขึ้น - การส่งคืนค่าว่างจะทำให้ผู้บริโภคสับสน (เมื่อ NPE เกิดขึ้น) ว่าสิ่งนี้ถูกส่งกลับโดยเจตนาหรือไม่ ดังนั้นคุณต้องตรวจสอบ javadoc เพื่อดูรายละเอียดเพิ่มเติม . การใช้ตัวเลือกค่อนข้างตรงไปตรงมา
2. ด้วย Optional คุณสามารถหลีกเลี่ยง NPE ได้อย่างสมบูรณ์ ตามที่กล่าวไว้ข้างต้น การใช้ Optional.ofNullable หรือ Else และ orElseGet สามารถทำให้เราอยู่ห่างจาก NPE
ผู้ช่วยให้รอดอีกคน!
ดูข้อมูลโค้ดนี้และคัดลอกโค้ดด้านล่าง:
แพ็คเกจ com.abhirockzz.wordpress.npesaviors;
นำเข้า java.util.Map;
นำเข้า java.util.Objects;
คลาสสาธารณะโดยใช้Objects {
สตริง getVal (แมป <สตริง, สตริง> aMap, คีย์สตริง) {
ส่งคืน aMap.containsKey(คีย์) ? aMap.get(คีย์) : null;
-
โมฆะคงที่สาธารณะ main (String [] args) {
การใช้Objects obj = ใหม่ การใช้Objects();
obj.getVal(null, "จำลอง");
-
-
อันไหนอาจจะว่างเปล่า?
1.วัตถุแผนที่
2. คีย์ที่ใช้ในการค้นหา
3. ตัวอย่างของการเรียกเมธอดนี้
หาก NPE ถูกโยนทิ้ง เราจะทราบได้อย่างไรว่าอันไหนเป็นโมฆะ
คัดลอกรหัสรหัสดังต่อไปนี้:
แพ็คเกจ com.abhirockzz.wordpress.npesaviors;
นำเข้า java.util.Map;
นำเข้า java.util.Objects;
คลาสสาธารณะโดยใช้Objects {
สตริง getValSafe (แมป <สตริง, สตริง> aMap, คีย์สตริง) {
แผนที่ <สตริง, สตริง> safeMap = Objects.requireNonNull(aMap,
"แผนที่เป็นโมฆะ");
String safeKey = Objects.requireNonNull (คีย์ "คีย์เป็นโมฆะ");
ส่งคืน safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null;
-
โมฆะคงที่สาธารณะ main (String [] args) {
การใช้Objects obj = ใหม่ การใช้Objects();
obj.getValSafe(null, "จำลอง");
-
-
needNonNull วิธีการ
1. หากวัตถุไม่เป็นโมฆะ ให้ส่งคืนตัวมันเอง
2. หากค่าเป็นโมฆะ NPE ที่ส่งคืนจะมีข้อความที่ระบุ
ทำไมมันถึงดีกว่า if(myObj!=null)?
การติดตามสแต็กที่คุณเห็นจะเห็นการเรียกเมธอด Objects.requireNonNull อย่างชัดเจน เมื่อรวมกับบันทึกข้อผิดพลาดของคุณเอง จะช่วยให้คุณค้นหาปัญหาได้เร็วขึ้น - - อย่างน้อยมันก็เร็วกว่าในความคิดของฉัน
คุณยังสามารถปรับแต่งเครื่องมือตรวจสอบของคุณเองได้ เช่น การใช้เครื่องมือตรวจสอบแบบธรรมดาเพื่อให้แน่ใจว่าไม่มีค่าว่าง
คัดลอกรหัสรหัสดังต่อไปนี้:
นำเข้า java.util.Collections;
นำเข้า java.util.List;
นำเข้า java.util.Objects;
นำเข้า java.util.function.Predicate;
RandomGist คลาสสาธารณะ {
สาธารณะคงที่ <T> T needNonEmpty (วัตถุ T, ภาคแสดง <T>, สตริง msgToCaller){
Objects.requireNonNull (วัตถุ);
Objects.requireNonNull (ภาคแสดง);
ถ้า (ภาคแสดง.test(วัตถุ)){
โยน IllegalArgumentException ใหม่ (msgToCaller);
-
คืนวัตถุ;
-
โมฆะคงที่สาธารณะ main (String [] args) {
//การใช้งาน 1: สตริงว่าง (โดยเจตนา)
สตริง s = "";
System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "สตริงของฉันว่างเปล่า!"));
//การใช้งาน 2: รายการว่าง (โดยเจตนา)
รายการ รายการ = Collections.emptyList();
System.out.println(requireNonEmpty(Objects.requireNonNull(list), (l) -> l.isEmpty(), "รายการว่างเปล่า!").size());
//การใช้งาน 3: ผู้ใช้ที่ว่างเปล่า (โดยเจตนา)
ผู้ใช้ ผู้ใช้ = ผู้ใช้ใหม่ ("");
System.out.println(requireNonEmpty(Objects.requireNonNull(ผู้ใช้), (u) -> u.getName().isEmpty(), "ผู้ใช้ว่างเปล่า!"));
-
ผู้ใช้คลาสคงที่ส่วนตัว {
ชื่อสตริงส่วนตัว
ผู้ใช้สาธารณะ (ชื่อสตริง) {
this.name = ชื่อ;
-
สตริงสาธารณะ getName(){
ชื่อผู้ส่งคืน;
-
-
-
อย่าปล่อยให้ NPE กลายเป็นความเจ็บปวดผิดที่ เรามีเครื่องมือมากมายที่จะจัดการกับ NPE ได้ดียิ่งขึ้นและยังกำจัดพวกมันให้หมดสิ้นอีกด้วย!