Il tuo errore principale è che stai ancora pensando in termini più procedurali. Questo non è inteso come una critica a te come persona, è semplicemente un'osservazione. Pensare in termini più funzionali arriva con il tempo e la pratica, e quindi i metodi sonoPresent e sembrano le cose più ovvie e corrette da chiamare per te. Il tuo errore secondario secondario sta creando l'Opzionale all'interno del tuo metodo. L'opzionale ha lo scopo di aiutare a documentare che qualcosa può o meno restituire un valore. Non potresti ottenere nulla.
Questo ti ha portato a scrivere un codice perfettamente leggibile che sembra perfettamente ragionevole, ma sei stato sedotto dai vili tentatori gemelli che ottengono ed èPresente.
Naturalmente la domanda diventa rapidamente "perché isPresent e arriva anche lì?"
Una cosa che molte persone qui mancano è che isPresent () è che non è qualcosa che è fatto per il nuovo codice scritto da persone completamente a bordo con come sono le lambda dannatamente utili e a chi piace la cosa funzionale.
Tuttavia, ci offre alcuni (due) buoni, fantastici, glamour (?) Vantaggi:
- Facilita la transizione del codice legacy per utilizzare le nuove funzionalità.
- Facilita le curve di apprendimento di Opzionale.
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 hai avuto una classe legacy usando questo come tale (riempi gli spazi):
Snickers lastSnickers = snickersCounter.lastConsumedSnickers();
if(null == lastSnickers) {
throw new NoSuchSnickersException();
}
else {
consumer.giveDiabetes(lastSnickers);
}
Un esempio inventato per essere sicuro. Ma abbi pazienza qui.
Java 8 è stato lanciato e stiamo cercando di salire a bordo. Quindi una delle cose che facciamo è che vogliamo sostituire la nostra vecchia interfaccia con qualcosa che renda Opzionale. Perché? Perché come qualcun altro ha già gentilmente citato:
questo elimina le congetture sul fatto che qualcosa possa essere nullo.
Questo è già stato sottolineato da altri. Ma ora abbiamo un problema. Immagina di avere (mi scusi mentre premo alt + F7 su un metodo innocente), 46 posti in cui questo metodo viene chiamato in un codice legacy ben testato che fa un lavoro eccellente altrimenti. Ora devi aggiornare tutti questi.
QUESTO è dove brilla isPresent.
Perché ora: Snickers lastSnickers = snickersCounter.lastConsumedSnickers (); if (null == lastSnickers) {throw new NoSuchSnickersException (); } else {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 esplorerà la base di codice allo stesso tempo. win-win. Dopotutto, qualcosa di simile a questo modello è piuttosto diffuso. E ora non devi riscrivere il codice per usare lambdas o altro. (In questo caso particolare sarebbe banale, ma lascio pensare a esempi in cui sarebbe difficile come esercizio per il lettore.)
Nota che ciò significa che il modo in cui lo hai fatto è essenzialmente un modo per gestire il codice legacy senza effettuare costose riscritture. E il nuovo codice?
Bene, nel tuo caso, dove vuoi solo stampare qualcosa, dovresti semplicemente fare:
. SnickersCounter.lastConsumedSnickers () ifPresent (System.out :: println);
Che è piuttosto semplice e perfettamente chiaro. Il punto che gorgoglia lentamente verso la superficie, quindi, è che esistono casi d'uso per get () e isPresent (). Sono lì per permetterti di modificare meccanicamente il codice esistente per utilizzare i tipi più recenti senza pensarci troppo. Ciò che stai facendo è quindi errato nei seguenti modi:
- Stai chiamando un metodo che potrebbe restituire null. L'idea corretta sarebbe che il metodo restituisca null.
- Stai usando i metodi legid legacy per gestire questo opzionale, invece di usare i nuovi gustosi metodi che contengono fantasia di lambda.
Se si desidera utilizzare Opzionale come semplice controllo di sicurezza null, ciò che si dovrebbe fare è semplicemente questo:
new Optional.ofNullable(employeeServive.getEmployee())
.map(Employee::getId)
.ifPresent(System.out::println);
Naturalmente, la bella versione di questo sembra:
employeeService.getEmployee()
.map(Employee::getId)
.ifPresent(System.out::println);
A proposito, anche se non è assolutamente necessario, ti consiglio di utilizzare una nuova riga per operazione, in modo che sia più facile da leggere. Facile da leggere e comprendere batte la concisione 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 nota come in questo esempio, ciò che stiamo esprimendo sono le nostre intenzioni. Vogliamo ottenere il dipendente, ottenere il suo documento d'identità 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 da poterlo alimentare su una mappa è in generale una buona idea.