Recentemente li sobre isso e vi pessoas usando essa classe, mas em quase todos os casos, usar null
também funcionaria - se não de forma mais intuitiva. Alguém pode dar um exemplo concreto de onde Optional
conseguiria algo que null
não poderia ou de uma forma muito mais limpa? A única coisa que posso pensar é em usá-lo com chaves Maps
que não aceitam null
, mas mesmo isso poderia ser feito com um "mapeamento" lateral do valor de null. Alguém pode me fornecer um argumento mais convincente? Obrigado.
89
Respostas:
Membro da equipe Guava aqui.
Provavelmente, a maior desvantagem de
null
é que não é óbvio o que deveria significar em qualquer contexto: ele não tem um nome ilustrativo. Nem sempre é óbvio quenull
significa "nenhum valor para este parâmetro" - diabos, como um valor de retorno, às vezes significa "erro", ou mesmo "sucesso" (!!), ou simplesmente "a resposta correta não é nada".Optional
é frequentemente o conceito que você realmente quer dizer quando torna uma variável anulável, mas nem sempre. Quando não for, recomendamos que você escreva sua própria classe, semelhante a,Optional
mas com um esquema de nomenclatura diferente, para deixar claro o que você realmente quer dizer.Mas eu diria que a maior vantagem de
Optional
não está na legibilidade: a vantagem é sua prova de idiota. Ele força você a pensar ativamente sobre o caso ausente se você deseja que seu programa compile, já que você tem que desembrulhar ativamente oOptional
e resolver esse caso. Null torna perturbadoramente fácil simplesmente esquecer as coisas e, embora FindBugs ajude, não acho que resolva o problema tão bem. Isso é especialmente relevante quando você retorna valores que podem ou não estar "presentes". Você (e outros) são muito mais propensos a esquecer queother.method(a, b)
poderia retornar umnull
valor do que é provável que você se esqueça de quea
poderia sernull
quando você está implementandoother.method
. RetornandoOptional
torna impossível para os chamadores esquecerem esse caso, uma vez que eles próprios precisam desembrulhar o objeto.Por esses motivos, recomendamos que você use
Optional
como um tipo de retorno para seus métodos, mas não necessariamente em seus argumentos de método.(A propósito, isso é totalmente baseado na discussão aqui ).
fonte
Map
retornanull
se uma chave não estiver mapeada, mas lembre-se de que se você fizer issomap.put(key, null)
,map.containsKey(key)
retornará,true
masmap.get(key)
retornaránull
.Optional
pode ser útil para esclarecer a distinção entre o caso "explicitamente mapeado para nulo" e o caso "não presente no mapa". Admito queOptional
pode haver abuso, mas ainda não estou convencido de que o caso que você descreve seja um abuso.Optional<T>
é esse valor "encontrado, mas não válido". Ou, mais precisamente,Optional<T>
é uma maneira de decorar qualquer tipoT
com um valor extra "encontrado, mas não válido" - criando um novo tipo combinando dois tipos existentes. Se você tiver cem classes, pode ficar complicado ter que criar um valor "encontrado, mas não válido" separado para cada uma, masOptional<T>
pode funcionar facilmente para todas elas.Realmente se parece com o
Maybe
padrão Monad de Haskell.Você deve ler o seguinte, Wikipedia Monad (programação funcional) :
E leia Do Opcional à Mônada com Goiaba no Blog de Kerflyn, que discute sobre o Opcional da Goiaba usada como Mônada:
Edit: Com Java8, há um opcional embutido que possui operadores monádicos como
flatMap
. Este tem sido um assunto controverso, mas finalmente foi implementado.Consulte http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html
O
flatMap
operador é essencial para permitir operações monádicas e permite encadear facilmente chamadas que retornem resultados opcionais.Pense nisso, se você usasse o
map
operador 5 vezes, acabaria com umOptional<Optional<Optional<Optional<Optional<String>>>>>
, enquanto o usoflatMap
daria a vocêOptional<String>
Desde Java8 eu prefiro não usar Guava's Optional que é menos poderoso.
fonte
Um bom motivo para usá-lo é que torna seus valores nulos muito significativos. Em vez de retornar um nulo que pode significar muitas coisas (como erro, falha ou vazio, etc), você pode colocar um 'nome' em seu nulo. Veja este exemplo:
vamos definir um POJO básico:
}
Agora vamos usar este POJO simples:
Agora vamos evitar o uso de nulo e fazer nossas verificações com Opcional para que seja significativo
portanto, no final, é uma maneira de tornar os nulos significativos e menos ambigüos.
fonte
A vantagem mais importante de Optional é que ele adiciona mais detalhes ao contrato entre o implementador e o responsável pela chamada de uma função. Por esse motivo, é útil para parâmetros e tipo de retorno.
Se você fizer a convenção de sempre ter
Optional
para possíveis objetos nulos, você adicionará mais esclarecimentos a casos como:Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)
O contrato aqui especifica claramente que há uma chance de um resultado não ser retornado, mas também mostra que funcionará com
from
eto
como ausente.Optional<Integer> maxPrime(Optional<Integer> from, Integer to)
O contrato especifica que de é opcional, portanto, um valor ausente pode ter um significado especial, como começar de 2. Posso esperar que um valor nulo para o
to
parâmetro lance uma exceção.Portanto, a parte boa de usar Optional é que o contrato se tornou descritivo (semelhante à
@NotNull
anotação), mas também formal, uma vez que você deve escrever código.get()
para lidar com eleOptional
.fonte