Seu erro principal é que você ainda está pensando em termos mais processuais. Isso não é uma crítica a você como pessoa, é apenas uma observação. Pensar em termos mais funcionais vem com o tempo e a prática, e, portanto, os métodos são apresentados e se parecem com as coisas corretas mais óbvias para você. Seu menor erro secundário é criar o seu Opcional dentro do seu método. O opcional destina-se a ajudar a documentar que algo pode ou não retornar um valor. Você pode não conseguir nada.
Isso levou você a escrever um código perfeitamente legível que parece perfeitamente razoável, mas você foi seduzido pelas vil gêmeas sedutoras que são atraídas e isPresent.
É claro que a questão rapidamente se torna "por que o isPresent e você chega lá?"
Uma coisa que muitas pessoas aqui sentem falta é que o Present () é que não é algo que é feito para um novo código escrito por pessoas com o quão desajeitadamente são os lambdas úteis e que gostam do funcional.
No entanto, ele nos dá alguns (dois) benefícios bons, ótimos, glamourosos (?):
- Facilita a transição do código legado para usar os novos recursos.
- Facilita as curvas de aprendizado do Opcional.
O primeiro é bastante simples.
Imagine que você tem uma API assim:
public interface SnickersCounter {
/**
* Provides a proper count of how many snickers have been consumed in total.
*/
public SnickersCount howManySnickersHaveBeenEaten();
/**
* returns the last snickers eaten.<br>
* If no snickers have been eaten null is returned for contrived reasons.
*/
public Snickers lastConsumedSnickers();
}
E você tinha uma classe legada usando isso (preencha os espaços em branco):
Snickers lastSnickers = snickersCounter.lastConsumedSnickers();
if(null == lastSnickers) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers);
}
Um exemplo inventado para ter certeza. Mas tenha paciência comigo aqui.
O Java 8 já foi lançado e estamos nos esforçando para embarcar.
Então, uma das coisas que fazemos é substituir a antiga interface por algo que retorne Opcional.
Por quê?
Porque, como alguém já mencionou graciosamente:
Isto elimina a adivinhação se algo pode ou não ser nulo
Isso já foi apontado por outros. Mas agora nós temos um problema. Imagine que temos (desculpe-me enquanto eu acertei alt + F7 em um método inocente), 46 lugares onde esse método é chamado em código legado bem testado que faz um excelente trabalho de outra forma. Agora você precisa atualizar tudo isso.
ESTE é onde isPresent brilha.
Porque agora:
Snickers lastSnickers = snickersCounter.lastConsumedSnickers ();
if (null == lastSnickers) {
lançar novo NoSuchSnickersException ();
}
outro {
consumer.giveDiabetes (lastSnickers);
}
torna-se:
Optional<Snickers> lastSnickers = snickersCounter.lastConsumedSnickers();
if(!lastSnickers.isPresent()) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers.get());
}
E essa é uma mudança simples que você pode dar ao novo júnior: ele pode fazer algo útil e explorar a base de código ao mesmo tempo. ganha-ganha. Afinal, algo semelhante a esse padrão é bastante difundido. E agora você não precisa reescrever o código para usar lambdas ou qualquer outra coisa.
(Neste caso em particular, seria trivial, mas deixo exemplos de pensamento onde seria difícil como um exercício para o leitor.)
Observe que isso significa que a maneira como você fez isso é essencialmente uma forma de lidar com o código legado sem fazer reescritas dispendiosas. Então, e o novo código?
Bem, no seu caso, onde você quer imprimir algo, você simplesmente faria:
snickersCounter.lastConsumedSnickers (). ifPresent (System.out :: println);
O que é bem simples e perfeitamente claro.
O ponto que está lentamente subindo até a superfície, é que existem casos de uso para get () e isPresent (). Eles estão lá para permitir que você modifique o código existente mecanicamente para usar os tipos mais recentes sem pensar muito sobre isso.
O que você está fazendo é, portanto, mal orientado das seguintes maneiras:
- Você está chamando um método que pode retornar null. A ideia correta seria que o método retorna null.
- Você está usando os métodos legados bandaid para lidar com isso como opcional, em vez de usar os novos métodos saborosos que contêm o conteúdo lambda.
Se você quiser usar o Opcional como uma simples verificação de segurança nula, o que você deveria ter feito é simplesmente isto:
new Optional.ofNullable(employeeServive.getEmployee())
.map(Employee::getId)
.ifPresent(System.out::println);
É claro que a boa aparência disso parece:
employeeService.getEmployee()
.map(Employee::getId)
.ifPresent(System.out::println);
A propósito, apesar de não ser obrigatório, recomendo usar uma nova linha por operação, para facilitar a leitura.
Fácil de ler e entender, conciliação em qualquer dia da semana.
Este é, obviamente, um exemplo muito simples, onde é fácil entender tudo o que estamos tentando fazer. Nem sempre é tão simples na vida real. Mas observe como neste exemplo, o que estamos expressando são nossas intenções. Queremos obter o funcionário, obter seu ID e, se possível, imprimi-lo. Esta é a segunda grande vitória com o Opcional. Isso nos permite criar um código mais claro. Eu também acho que fazer coisas como criar um método que faça um monte de coisas para que você possa alimentá-lo em um mapa é, em geral, uma boa ideia.