เหตุใดจึงต้องใช้ตัวเลือกมากกว่าตัวเลือก


232

เมื่อใช้OptionalคลาสJava 8 มีสองวิธีในการห่อค่าในตัวเลือก

String foobar = <value or null>;
Optional.of(foobar);         // May throw NullPointerException
Optional.ofNullable(foobar); // Safe from NullPointerException

ฉันเข้าใจว่าOptional.ofNullableเป็นวิธีเดียวที่ปลอดภัยในการใช้Optionalแต่ทำไมถึงOptional.ofมีอยู่จริง? ทำไมไม่ใช้เพียงOptional.ofNullable และอยู่ข้างปลอดภัยตลอดเวลา?


1
โปรดบอกฉันว่าแพคเกจใดที่ต้องนำเข้ามาใช้?
LoveToCode

4
@LoveToCode java.util.Optional- ใช้งานได้ถ้าคุณใช้ JDK 8 หรือใหม่กว่า
whirlwin

11
ฉันจะรักถ้าพวกเขาจะมีofNullable()ชื่อof()และof()ตั้งชื่อofNotNull()
Robert Niestroj


ในขณะที่คุณถามว่า "ทำไมมีตัวเลือกอยู่ด้วยทำไมไม่ใช้ตัวเลือกถ้าไม่สามารถใช้ได้และอยู่ในตำแหน่งที่ปลอดภัยตลอดเวลา" สมมติว่าหากไม่มีข้อมูลที่จำเป็นของผู้ใช้เราจะต้องทำการยกเว้น ดังนั้นทั้งหมดขึ้นอยู่กับกรณีของคุณ baeldung.com/java-optional-throw-exception
Karan Arora

คำตอบ:


306

คำถามของคุณขึ้นอยู่กับการสันนิษฐานว่ารหัสที่อาจส่งไปNullPointerExceptionนั้นแย่กว่ารหัสที่อาจไม่ได้รับ สมมติฐานนี้ผิด หากคุณคาดว่าโปรแกรมของคุณfoobarจะไม่เป็นโมฆะเนื่องจากตรรกะของโปรแกรมOptional.of(foobar)คุณควรใช้โปรแกรมดังกล่าวเพื่อดูNullPointerExceptionว่าโปรแกรมของคุณมีข้อบกพร่องหรือไม่ หากคุณใช้Optional.ofNullable(foobar)และสิ่งที่foobarเกิดขึ้นnullเนื่องจากข้อผิดพลาดจากนั้นโปรแกรมของคุณจะทำงานต่ออย่างไม่ถูกต้องอย่างเงียบ ๆ ซึ่งอาจเป็นภัยพิบัติที่ใหญ่กว่า วิธีนี้อาจเกิดข้อผิดพลาดได้ในภายหลังและจะยากกว่าที่จะเข้าใจในจุดที่ผิดพลาด


129
" ถ้าคุณคาดหวังว่า foobar ของคุณจะไม่เป็นโมฆะเนื่องจากตรรกะของโปรแกรมจะดีกว่าการใช้Optional.of(foobar)มาก" ดูเหมือนว่าจะแปลกไปหน่อย - เมื่อเรารู้ว่าค่าจะไม่เป็นnullเช่นนั้นแล้วทำไมไม่ใช้ค่าของมันเองแทนที่จะห่อมันไว้ภายในOptional?
Konstantin Yovkov

54
@kocko คุณอาจต้องส่งคืนOptionalเมธอดดังกล่าวจากอินเทอร์เฟซที่คุณใช้งาน (ผู้ดำเนินการรายอื่นอาจส่งคืนทางเลือกที่ว่างเปล่า) หรือคุณต้องการสร้างคอลเลกชัน / สตรีมของตัวเลือกซึ่งบางอันมีการรับประกันว่าไม่เป็นโมฆะและบางรายการไม่ หรือคุณมีเงื่อนไขแบบลอจิคัลซึ่งสร้างทางเลือกในหลาย ๆ สาขาและในสาขาเดียวคุณแน่ใจว่ามันไม่ใช่ค่าว่าง
Tagir Valeev

28
เพราะทางเลือกหมายความว่าสามารถมีอยู่หรือไม่อยู่ หายไป! = null nullในกรณีนี้หมายถึง "ฉันคาดว่า foobar จะมีอยู่ แต่เนื่องจากข้อผิดพลาดมันเป็นโมฆะ" Optional.isPresent() == falseหมายความว่าไม่มีแถบ foobar นั่นคือสิ่งที่คาดหวังพฤติกรรมที่ชอบด้วยกฎหมาย
Buurman

43
@kocko: ตัวอย่างง่ายๆคาดว่าจะไม่เคยมีค่า ...return list.isEmpty()? Optional.empty(): Optional.of(list.get(0));listnull
โฮล

5
@Harish ถ้าคุณถามฉันฉันไม่แนะนำให้ใช้ตัวเลือกทุกที่ นั่นเป็นคำถามแยกต่างหาก คุณสามารถตรวจสอบความคิดเห็นของบางอย่างที่นี่
Tagir Valeev

12

นอกจากนี้หากคุณรู้ว่ารหัสของคุณไม่ควรทำงานหากวัตถุเป็นโมฆะคุณสามารถใช้ข้อยกเว้นได้ Optional.orElseThrow

String nullName = null;
String name = Optional.ofNullable(nullName).orElseThrow(NullPointerException::new);

1
แต่สำหรับสิ่งนี้คุณสามารถใช้ที่สั้นกว่านี้ได้String name = Objects.requireNonNull(nullName);
Holger

1
จุดดี @Holger อย่างไรก็ตาม. orElse () วิธีการช่วยให้ข้อยกเว้นที่กำหนดเองที่อาจช่วยให้คุณจัดการการไหลของการควบคุมหรือการบันทึกข้อมูลที่ดีขึ้น
Nikos Stais

1
คุณสามารถให้ข้อความยกเว้นเพื่อให้ข้อมูลเพิ่มเติม ความพยายามในการปรับแต่งอื่น ๆ เช่นการใช้ข้อยกเว้นที่แตกต่างจากNullPointerExceptionเมื่อปัญหาชัดเจนเป็นการอ้างอิงที่nullไม่ควรเป็นขั้นตอนในทิศทางที่ผิด
Holger

นอกจากนี้คุณสามารถใช้ตัวเลือกเพื่อโยนข้อยกเว้นที่เฉพาะเจาะจงมากขึ้น (เช่นกำหนดเอง) ไม่ใช่ NPE, NPE นั้นกว้างเกินไปคุณสามารถโยนสิ่งที่ต้องการได้new NullNameException("meaningful msg")
Dáve

1

ขึ้นอยู่กับสถานการณ์

สมมติว่าคุณมีฟังก์ชั่นทางธุรกิจบางอย่างและคุณจำเป็นต้องประมวลผลบางอย่างด้วยค่านั้นต่อไป แต่การมีnullค่าในเวลาของการประมวลผลจะส่งผลกระทบ

Optional<?>จากนั้นในกรณีที่คุณสามารถใช้

String nullName = null;

String name = Optional.ofNullable(nullName)
                      .map(<doSomething>)
                      .orElse("Default value in case of null");

0

ตัวเลือกควรใช้เป็นหลักสำหรับผลลัพธ์ของบริการอย่างไรก็ตาม ในการบริการที่คุณรู้ว่าสิ่งที่คุณมีอยู่ในมือและกลับมาตัวเลือกของ (someValue) ถ้าคุณมีผลลัพธ์และกลับมาตัวเลือกถ้าไม่ว่าง () ถ้าคุณไม่ได้ ในกรณีนี้ค่าบางอย่างไม่ควรเป็นโมฆะและคุณจะส่งกลับทางเลือก


1
ขอบคุณสำหรับการแก้ไข Sumesh แต่ "someValue" ในบรรทัดสุดท้ายที่คุณแก้ไขให้เป็น "some value" อ้างอิงตัวแปรใน "Optional.of (someValue)" ด้านบนและควรอยู่ที่มูลค่าบางอย่างฉันคิดว่า
espendennis
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.