Por que usar Optional.of sobre Optional.ofNullable?

232

Ao usar a Optionalclasse Java 8 , há duas maneiras pelas quais um valor pode ser agrupado em um opcional.

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

Entendo que Optional.ofNullableé a única maneira segura de usar Optional, mas por que Optional.ofexiste? Por que não usar Optional.ofNullable e estar sempre seguro?

turbilhão
fonte
1
por favor me diga qual pacote deve importar para usar isso?
LoveToCode
4
@LoveToCode java.util.Optional- Ele está disponível se você estiver usando JDK 8 ou posterior
whirlwin
11
Eu adoraria se eles teriam ofNullable()nomeado of()e of()nomeadoofNotNull()
Robert Niestroj
Consulte baeldung.com/java-optional
Sumesh TG,
Como você está perguntando "por que o Optional.of existe? Por que não usar o Optional.ofNullable e estar sempre seguro?" Digamos que se os dados necessários do usuário não estiverem presentes, devemos lançar uma exceção. Portanto, depende totalmente do seu caso. baeldung.com/java-optional-throw-exception
Karan Arora

Respostas:

306

Sua pergunta é baseada na suposição de que o código que pode lançar NullPointerExceptioné pior do que o código que não pode. Esta suposição está errada. Se você espera que o seu foobarnunca seja nulo devido à lógica do programa, é muito melhor usá- Optional.of(foobar)lo, pois você verá um NullPointerExceptionque indicará que seu programa tem um bug. Se você usar Optional.ofNullable(foobar)e foobarisso ocorrer nulldevido ao erro, seu programa continuará silenciosamente funcionando incorretamente, o que pode ser um desastre ainda maior. Dessa forma, um erro pode ocorrer muito mais tarde e seria muito mais difícil entender em que ponto ele deu errado.

Tagir Valeev
fonte
129
" Se você espera que o seu foobar nunca seja nulo devido à lógica do programa, é muito melhor usá-loOptional.of(foobar) ". Isso parece um pouco estranho - quando sabemos que o valor não será de nullforma alguma, por que não usar o próprio valor, em vez de agrupá-lo em um Optional?
Konstantin Yovkov 29/07
54
@kocko, pode ser necessário retornar o Optionalmétodo conforme exigido pela interface que você está implementando (provavelmente outros implementadores podem retornar um opcional vazio). Ou você deseja criar uma coleção / fluxo de opcionais, alguns dos quais são garantidos como não nulos e outros não. Ou você tem uma lógica condicional que cria um opcional em várias ramificações e na única ramificação você tem certeza de que não é nulo.
Tagir Valeev
28
Porque Opcional significa que ele pode estar presente ou ausente. Ausente! = Nulo. nullneste caso, significa "Espero que o foobar esteja presente, mas devido a um erro, ele é nulo". Optional.isPresent() == falsesignifica que foobar não está presente, isto é, é esperado, comportamento legítimo.
Buurman 29/07
43
@kocko: exemplo simples: return list.isEmpty()? Optional.empty(): Optional.of(list.get(0));a listespera-se que nunca contêm nullvalores ...
Holger
5
@ Harish, se você está me perguntando, não aconselho usar opcionais em qualquer lugar. Essa é uma pergunta separada. Você pode conferir algumas opiniões aqui .
Tagir Valeev
12

Além disso, se você souber que seu código não funcionará se o objeto for nulo, você poderá lançar uma exceção usando Optional.orElseThrow

String nullName = null;
String name = Optional.ofNullable(nullName).orElseThrow(NullPointerException::new);
Karan Arora
fonte
1
Mas para isso, você pode usar o mesmo mais curtoString name = Objects.requireNonNull(nullName);
Holger
1
Bom ponto @Holger, no entanto, o método .orElse () permite exceções personalizadas que podem ajudá-lo a lidar melhor com o fluxo de controle ou com o registro de informações.
Nikos Stais 17/11/19
1
Bem, você pode fornecer uma mensagem para a exceção para fornecer informações adicionais. Qualquer outra tentativa de customização, como usar uma exceção diferente de NullPointerExceptionquando o problema é claramente uma referência que é nullenquanto não deveria, seria um passo na direção errada.
Holger
Além disso, você pode usar o Opcional para lançar uma exceção mais específica (por exemplo, personalizada), não o NPE, o NPE é muito genérico, você pode lançar algo comonew NullNameException("meaningful msg")
Dáve
1

Isso depende dos cenários.

Digamos que você tenha alguma funcionalidade comercial e precise processar algo com esse valor ainda mais, mas ter nullvalor no momento do processamento afetaria isso.

Então, nesse caso, você pode usar Optional<?>.

String nullName = null;

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

De qualquer forma, opcional deve ser usado principalmente para resultados de Serviços. No serviço, você sabe o que tem em mãos e retorna Optional.of (someValue) se tiver um resultado e retorna Optional.empty () se não tiver. Nesse caso, algum valor nunca deve ser nulo e ainda assim, você retorna um Opcional.

espendennis
fonte
1
Obrigado pela edição Sumesh, mas o "someValue" na última linha que você editou como "some Value", referencia a variável em "Optional.of (someValue)" acima e deve permanecer someValue, eu acho.
espendennis 13/09/18