
ทางเลือกคืออะไร?
พารามิเตอร์ทางเลือกใช้ในการพกพาออบเจ็กต์และเปิดใช้งานการอ้างอิง nullที่จะจัดการโดย API ต่างๆ ลองดูข้อมูลโค้ด:Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
เรามี ตัวอย่าง กาแฟที่เราได้รับน้ำตาลจากอินสแตนซ์ของวัตถุน้ำตาล หากเราถือว่าค่าปริมาณไม่เคยถูกตั้งค่าในตัว สร้าง Coffeeดังนั้นcoffee.getSugar().getQuantity()จะส่งคืนค่าNullPointerException แน่นอนว่าเราสามารถใช้ การตรวจสอบ ค่าว่างแบบ เก่าที่ดี เพื่อแก้ไขปัญหาได้ เสมอ
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
quantity = coffee.getSugar().getQuantity();
}
ตอนนี้ทุกอย่างดูเหมือนจะดี แต่เมื่อเขียนโค้ด Java เราควรหลีกเลี่ยงการใช้ การตรวจ สอบค่าว่าง เรามาดูกันว่าสามารถทำได้โดยใช้ตัวเลือกเสริม
วิธีการสร้างทางเลือก
มีสามวิธีในการสร้างออบเจ็กต์เสริม:-
ของ (ค่า T) - การสร้างอินสแตนซ์ของวัตถุเสริมที่ไม่ใช่ค่าว่าง โปรดทราบว่าการใช้()เพื่ออ้างถึงวัตถุnullจะทำให้เกิดNullPointerException
-
ofNullable(ค่า T) - สร้างค่าเสริมสำหรับวัตถุที่สามารถเป็นค่าว่างได้
-
ว่างเปล่า() - สร้างอินสแตน ซ์ทางเลือกที่แสดงถึงการอ้างอิงถึงnull
// пример использования Optional.of(T Value)
String name = "foo";
Optional<String> stringExample = Optional.of(name)
// пример использования Optional.ofNullable(T Value)
Integer age = null;
Optional<Integer> integerExample= Optional.ofNullable(age)
// пример использования Optional.empty()
Optional<Object> emptyExample = Optional.empty();
ดังนั้นคุณจึงมีวัตถุเสริม ตอนนี้เรามาดูสองวิธีหลักสำหรับตัวเลือกเสริม:
-
isPresent() - เมธอดนี้จะบอกคุณว่าออบเจ็กต์เสริมมีค่าที่ไม่ใช่ค่าว่างหรือไม่
-
get() - รับค่าของ Optional ด้วยค่าปัจจุบัน โปรดทราบว่าการเรียกget()บนตัวเลือกว่างจะส่งผลให้เกิดNullPointerException
การปรับปรุงการตรวจสอบ Null ด้วยตัวเลือก
แล้วเราจะปรับปรุงโค้ดข้างต้นได้อย่างไร? ด้วย Optional เราสามารถเข้าใจการมีอยู่ของวัตถุโดยใช้isPresent()และดึงข้อมูลโดยใช้get( ) เริ่มต้นด้วยการ บรรจุผลลัพธ์ของcoffee.getSugar()ด้วย Optional และใช้ เมธอด isPresent() สิ่งนี้จะช่วยเราพิจารณาว่าgetSugar() ส่งคืน ค่าว่างหรือไม่Coffee coffee = new Coffee();
Optional<String> sugar = Optional.ofNullable(coffee.getSugar());
int quantity = 0;
if (sugar.isPresent()) {
Sugar sugar = sugar.get();
int quantity = sugar.getQuantity();
}
จากตัวอย่างนี้ การบรรจุผลลัพธ์ของcoffee.getSugar()ลงใน Optional ดูเหมือนจะไม่เพิ่มมูลค่าใดๆ แต่เพิ่มความยุ่งยาก เราสามารถปรับปรุงผลลัพธ์ได้โดยใช้สิ่งที่ฉันคิดว่าเป็นฟังก์ชันโปรดของฉันจากคลาสเสริม:
-
map(Function<? super T,? extensions U> mapper) - จับคู่ค่าที่มีอยู่ใน Optional กับฟังก์ชันที่ให้มา หากพารามิเตอร์ Optional ว่างเปล่า ดังนั้นmap()จะส่งกลับOptional.empty( )
-
orElse ( T other)เป็นเวอร์ชัน "พิเศษ" ของ เมธอด get() สามารถรับค่าที่อยู่ในตัวเลือกได้ อย่างไรก็ตาม ในกรณีของ Optional ที่ว่าง เปล่าระบบจะส่งคืนค่าที่ส่งไปยัง เมธอด orElse()
Coffee coffee = new Coffee();
Integer quantity = Optional.ofNullable(coffee.getSugar())
.map(it -> it.getQuantity())
.orElse(0);
มันเจ๋งจริงๆ - อย่างน้อยฉันก็คิดอย่างนั้น ตอนนี้ หากในกรณีของค่าว่าง เราไม่ต้องการส่งคืนค่าเริ่มต้น เราจำเป็นต้องส่งข้อยกเว้นบางประเภท orElseThrow(Supplier<? ขยาย X> ข้อยกเว้นซัพพลายเออร์)ส่งคืนค่าที่มีอยู่ในพารามิเตอร์ทางเลือก หรือส่งข้อยกเว้นหากตัวเลือกว่างเปล่า
Coffee coffee = new Coffee();
Integer quantity = Optional.ofNullable(coffee.getSugar())
.map(it -> it.getQuantity())
.orElseThrow(IllegalArgumentException::new);
อย่างที่คุณเห็น ตัวเลือกเสริม มีข้อดีหลายประการ:
- บทคัดย่อ การตรวจสอบ โมฆะ
- จัดเตรียม API สำหรับการจัดการ วัตถุ ว่าง
- อนุญาตให้มีแนวทางการประกาศเพื่อแสดงสิ่งที่กำลังประสบความสำเร็จ
วิธีที่จะมีประสิทธิภาพด้วยตัวเลือก
ในงานของฉัน ฉันใช้ Optional เป็นประเภทการส่งคืนเมื่อเมธอดสามารถส่งคืนสถานะ "ไม่มีผลลัพธ์" ฉันมักจะใช้มันเมื่อกำหนดประเภทการส่งคืนสำหรับวิธีการOptional<Coffee> findByName(String name) {
...
}
บางครั้งก็ไม่จำเป็น ตัวอย่างเช่น หากฉันมีเมธอดที่ส่งคืนintเช่นgetQuantity()ใน คลาส Sugarเมธอดนั้นอาจส่งคืน0หากผลลัพธ์เป็นnullเพื่อแสดงถึง "no quantity" เมื่อรู้สิ่งนี้แล้ว เราก็คิดได้ว่า พารามิเตอร์ Sugarใน คลาส Coffeeสามารถแสดงเป็นตัวเลือกได้ เมื่อมองแวบแรก ดูเหมือนว่าจะเป็นความคิดที่ดี เนื่องจากตามทฤษฎีแล้ว น้ำตาลไม่จำเป็นต้องมีอยู่ในกาแฟ อย่างไรก็ตาม นี่คือจุดที่ฉันต้องการกล่าวถึงเมื่อไม่ใช้ตัวเลือก เราควรหลีกเลี่ยงการใช้ตัวเลือกเสริมในสถานการณ์ต่อไปนี้:
-
เป็นประเภทพารามิเตอร์สำหรับPOJOเช่นDTO ตัวเลือกต่างๆ ไม่สามารถทำให้เป็นซีเรียลไลซ์ได้ ดังนั้นการใช้ตัวเลือกเหล่านั้นใน POJO จะทำให้อ็อบเจ็กต์ไม่สามารถซีเรียลไลซ์ได้
-
เป็นอาร์กิวเมนต์วิธีการ หากอาร์กิวเมนต์ของเมธอดสามารถเป็นnull ได้ ดังนั้นจากมุมมองของโค้ดล้วนๆ การส่งค่าnullยังคงดีกว่าการส่งผ่าน Optional นอกจากนี้ คุณสามารถสร้างวิธีการโอเวอร์โหลดเพื่อจัดการกับการไม่มีอาร์กิวเมนต์วิธีการ null ในทางนามธรรมได้
-
เพื่อแสดงถึงวัตถุคอลเลกชันที่หายไป คอลเลกชั่นสามารถว่างเปล่าได้ ดังนั้นคอลเลกชั่น ว่าง เช่นSetหรือList ที่ว่างเปล่า จะต้องถูกใช้เพื่อแสดงคอลเลกชั่นที่ไม่มีค่า
GO TO FULL VERSION