Tại sao nên sử dụng Options.of trên Options.ofNullable?


232

Khi sử dụng lớp Java 8 Optional, có hai cách trong đó một giá trị có thể được gói trong một tùy chọn.

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

Tôi hiểu Optional.ofNullablelà cách sử dụng an toàn duy nhất Optional, nhưng tại sao lại Optional.oftồn tại? Tại sao không chỉ sử dụng Optional.ofNullable và luôn an toàn?


1
Xin vui lòng cho tôi biết gói nào phải nhập để sử dụng này?
LoveToCode

4
@LoveToCode java.util.Optional- Nó khả dụng nếu bạn đang sử dụng JDK 8 trở lên
whirlwin

11
Tôi rất thích nếu họ ofNullable()đặt tên of()of()đặt tênofNotNull()
Robert Niestroj

Vui lòng tham khảo baeldung.com/java-optional
Sumesh TG

Như bạn đang hỏi "tại sao Options.of hoàn toàn tồn tại? Tại sao không chỉ sử dụng Options.ofNullable và luôn ở bên an toàn?" Giả sử nếu dữ liệu yêu cầu của người dùng không có mặt, thì chúng ta phải ném ngoại lệ. Vì vậy, nó hoàn toàn phụ thuộc vào usecase của bạn. baeldung.com/java-optional-throw-exception
Karan Arora

Câu trả lời:


306

Câu hỏi của bạn dựa trên giả định rằng mã có thể ném NullPointerExceptioncòn tệ hơn mã có thể không. Giả định này là sai. Nếu bạn mong đợi rằng bạn foobarkhông bao giờ là null do logic chương trình, thì tốt hơn Optional.of(foobar)là bạn nên sử dụng vì bạn sẽ thấy NullPointerExceptionchương trình của bạn có lỗi. Nếu bạn sử dụng Optional.ofNullable(foobar)foobarxảy ra nulldo lỗi, thì chương trình của bạn sẽ âm thầm tiếp tục hoạt động không chính xác, đây có thể là một thảm họa lớn hơn. Bằng cách này, một lỗi có thể xảy ra muộn hơn nhiều và sẽ khó hiểu hơn tại điểm mà nó đã sai.


129
" Nếu bạn mong đợi rằng foobar của bạn không bao giờ là null do logic chương trình, thì tốt hơn là sử dụngOptional.of(foobar) ". Điều này có vẻ hơi lạ - khi chúng ta biết rằng giá trị sẽ không có nulltrong mọi trường hợp, vậy thì tại sao không sử dụng chính giá trị đó, thay vì bọc nó trong một Optional?
Konstantin Yovkov

54
@kocko, bạn có thể phải trả về Optionaltừ phương thức theo yêu cầu của giao diện bạn đang triển khai (có thể những người triển khai khác có thể trả về một tùy chọn trống). Hoặc bạn muốn tạo một bộ sưu tập / luồng tùy chọn, một số trong số đó được đảm bảo không có giá trị và một số thì không. Hoặc bạn có logic điều kiện tạo ra một tùy chọn trong một số nhánh và trong một nhánh duy nhất, bạn chắc chắn rằng nó không có giá trị.
Tagir Valeev 29/07/2015

28
Bởi vì Tùy chọn có nghĩa là nó có thể có mặt, hoặc vắng mặt. Vắng mặt! = Null. nulltrong trường hợp này có nghĩa là "Tôi hy vọng foobar sẽ có mặt, nhưng do lỗi nên nó không có giá trị". Optional.isPresent() == falsecó nghĩa là foobar không có mặt, tức là điều này được mong đợi, hành vi hợp pháp.
Buurman

43
@kocko: ví dụ đơn giản: return list.isEmpty()? Optional.empty(): Optional.of(list.get(0));các listdự kiến sẽ không bao giờ chứa nullcác giá trị ...
Holger

5
@Harish nếu bạn hỏi tôi, tôi không khuyên bạn nên sử dụng Tùy chọn ở mọi nơi. Đó là một câu hỏi riêng biệt. Bạn có thể kiểm tra một số ý kiến ở đây .
Tagir Valeev

12

Ngoài ra, nếu bạn biết mã của mình không hoạt động nếu đối tượng là null, bạn có thể ném ngoại lệ bằng cách sử dụng Optional.orElseThrow

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

1
Nhưng đối với điều này, bạn có thể sử dụng thậm chí ngắn hơnString name = Objects.requireNonNull(nullName);
Holger

1
Tuy nhiên, điểm tốt @Holger, phương thức .orElse () cho phép các ngoại lệ tùy chỉnh có thể giúp bạn xử lý tốt hơn luồng kiểm soát hoặc ghi nhật ký thông tin.
Nikos Stais

1
Vâng, bạn có thể cung cấp một thông báo cho ngoại lệ để cung cấp thêm thông tin. Bất kỳ nỗ lực tùy chỉnh nào khác, như sử dụng một ngoại lệ khác với NullPointerExceptionkhi vấn đề rõ ràng là một tài liệu tham khảo nulltrong khi không nên, sẽ là một bước đi sai hướng.
Holger

Ngoài ra, bạn có thể sử dụng Tùy chọn để ném ngoại lệ cụ thể hơn (ví dụ: tùy chỉnh), không phải NPE, NPE quá chung chung, bạn có thể ném một cái gì đó nhưnew NullNameException("meaningful msg")
Dáve

1

Điều này phụ thuộc vào các kịch bản.

Giả sử bạn có một số chức năng kinh doanh và bạn cần xử lý một cái gì đó với giá trị đó hơn nữa nhưng có nullgiá trị tại thời điểm xử lý sẽ ảnh hưởng đến nó.

Sau đó, trong trường hợp đó, bạn có thể sử dụng Optional<?>.

String nullName = null;

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

0

Tùy chọn chủ yếu nên được sử dụng cho kết quả của Dịch vụ. Trong dịch vụ, bạn biết những gì bạn có trong tay và trả lại Tùy chọn.of (someValue) nếu bạn có kết quả và trả lại Tùy chọn.empty () nếu bạn không. Trong trường hợp này, một số giá trị sẽ không bao giờ là null và vẫn còn, bạn trả lại Tùy chọn.


1
Cảm ơn vì đã chỉnh sửa Sumesh, nhưng "someValue" trong dòng cuối cùng mà bạn đã chỉnh sửa thành "some Value", tham chiếu biến trong "Options.of (someValue)" ở trên và tôi nên giữ một sốValue, tôi nghĩ vậy.
đặc biệt
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.