Il tuo errore principale è che stai ancora pensando in termini più procedurali. Questo non è inteso come una critica a te come persona, è solo un'osservazione. Pensare in termini più funzionali arriva con il tempo e la pratica, e quindi i metodi sono presenti e appaiono come le cose più ovvie e corrette da chiamare per te. Il tuo errore secondario secondario è la creazione del tuo opzionale all'interno del tuo metodo. L'opzione Opzionale ha lo scopo di aiutare a documentare che qualcosa può o non può restituire un valore. Potresti non ottenere nulla.
Questo ti ha portato a scrivere codice perfettamente leggibile che sembra perfettamente ragionevole, ma sei stato sedotto dalle vili tentatrici gemelle che sono state ottenute e sono presenti.
Ovviamente la domanda diventa rapidamente "perché sono isPresent e arriva anche lì?"
Una cosa che manca a molte persone qui è che isPresent () è che non è qualcosa che è fatto per un nuovo codice scritto da persone pienamente a bordo con quanto siano utili lambdas e che amano la cosa funzionale.
Tuttavia, ci concede alcuni (due) vantaggi buoni, fantastici e glamour (?):
- Facilita la transizione del codice legacy per utilizzare le nuove funzionalità.
- Facilita le curve di apprendimento di Facoltativo.
Il primo è piuttosto semplice.
Immagina di avere un'API simile a questa:
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 avevi una classe legacy che usava questo (riempire gli spazi vuoti):
Snickers lastSnickers = snickersCounter.lastConsumedSnickers();
if(null == lastSnickers) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers);
}
Un esempio forzato per essere sicuro. Ma portami con me qui.
Java 8 è ora disponibile e stiamo cercando di salire a bordo.
Quindi, una delle cose che facciamo è che vogliamo sostituire la nostra vecchia interfaccia con qualcosa che restituisce Opzionale.
Perché?
Perché come qualcun altro ha già gentilmente menzionato:
Ciò consente di capire se qualcosa può essere nullo
Questo è già stato sottolineato da altri. Ma ora abbiamo un problema. Immaginiamo di avere (mi scusi mentre ho colpito alt + F7 su un metodo innocente), 46 luoghi in cui questo metodo è chiamato in codice legacy ben collaudato che fa un lavoro eccellente altrimenti. Ora devi aggiornare tutti questi elementi.
QUESTO è dove splende isPresent.
Perché ora:
Snickers lastSnickers = snickersCounter.lastConsumedSnickers ();
if (null == lastSnickers) {
lanciare nuovi NoSuchSnickersException ();
}
altro {
consumer.giveDiabetes (lastSnickers);
}
diventa:
Optional<Snickers> lastSnickers = snickersCounter.lastConsumedSnickers();
if(!lastSnickers.isPresent()) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers.get());
}
E questo è un semplice cambiamento che puoi dare al nuovo junior: può fare qualcosa di utile, e allo stesso tempo esplorerà il codice base. win-win. Dopotutto, qualcosa di simile a questo schema è abbastanza diffuso. E ora non devi riscrivere il codice per usare lambda o altro.
(In questo caso particolare sarebbe banale, ma lascio pensare a degli esempi in cui sarebbe difficile come esercizio per il lettore.)
Si noti che questo significa che il modo in cui lo si è fatto è essenzialmente un modo per gestire il codice legacy senza fare costose riscritture. Che dire del nuovo codice?
Bene, nel tuo caso, dove vuoi solo stampare qualcosa, devi semplicemente fare:
snickersCounter.lastConsumedSnickers () ifPresent (System.out :: println);.
Che è piuttosto semplice e perfettamente chiaro.
Il punto che sta lentamente ribollendo in superficie allora, è che esistono casi d'uso per get () e isPresent (). Sono lì per farti modificare il codice esistente meccanicamente per usare i nuovi tipi senza pensarci troppo.
Quello che stai facendo è quindi fuorviato nei seguenti modi:
- Stai chiamando un metodo che potrebbe restituire null. L'idea corretta sarebbe che il metodo restituisce null.
- Stai utilizzando i metodi legacy bandaid per gestire questa opzione, invece di utilizzare i nuovi e gustosi metodi che contengono lambda fanciness.
Se vuoi usare Opzionale come semplice controllo di sicurezza nulla, ciò che avresti dovuto fare è semplicemente questo:
new Optional.ofNullable(employeeServive.getEmployee())
.map(Employee::getId)
.ifPresent(System.out::println);
Naturalmente, la bella versione di questo aspetto è:
employeeService.getEmployee()
.map(Employee::getId)
.ifPresent(System.out::println);
A proposito, anche se non è assolutamente necessario, raccomando di usare una nuova riga per operazione, in modo che sia più facile da leggere.
Facile da leggere e capire la concisione di battiti in qualsiasi giorno della settimana.
Questo è ovviamente un esempio molto semplice in cui è facile capire tutto ciò che stiamo cercando di fare. Non è sempre così semplice nella vita reale. Ma notate come in questo esempio, ciò che stiamo esprimendo sono le nostre intenzioni. Vogliamo ottenere il dipendente, ottenere il suo ID e, se possibile, stamparlo. Questa è la seconda grande vittoria con Opzionale. Ci consente di creare un codice più chiaro. Penso anche che fare cose come fare un metodo che faccia un sacco di cose in modo che tu possa darle da mangiare a una mappa è in generale una buona idea.