JavaRush /Java Blog /Random-IT /Pausa caffè #161. Come gestire Null in Java utilizzando O...

Pausa caffè #161. Come gestire Null in Java utilizzando Opzionale

Pubblicato nel gruppo Random-IT
Fonte: Medium Questo articolo ti aiuterà a comprendere meglio lo scopo di Opzionale quando lavori con il codice Java. Pausa caffè #161.  Come gestire Null in Java utilizzando Opzionale - 1Quando ho iniziato a lavorare con il codice Java, mi è stato spesso consigliato di utilizzare Opzionale. Ma all'epoca non capivo perché usare Opzionale fosse meglio che implementare la gestione dei valori nulli. In questo articolo, voglio condividere con te il motivo per cui penso che dovremmo tutti utilizzare di più Opzionale e come evitare un'eccessiva opzionalizzazione del codice, che è dannosa per la qualità del codice.

Cos'è facoltativo?

Il parametro Opzionale viene utilizzato per trasportare oggetti e consentire la gestione dei riferimenti null da parte di varie API. Diamo un'occhiata allo snippet di codice:
Coffee coffee = new Coffee();
Integer quantity = coffee.getSugar().getQuantity();
Abbiamo un'istanza Coffee in cui otteniamo dello zucchero da un'istanza dell'oggetto Sugar . Se assumiamo che il valore della quantità non sia mai stato impostato nel costruttore Coffee , allora coffee.getSugar().getQuantity() restituirà una NullPointerException . Naturalmente, possiamo sempre utilizzare i buoni vecchi controlli null per risolvere il problema.
Coffee coffee = new Coffee();
Integer quantity = 0;
if (coffee.getSugar() != null) {
  quantity = coffee.getSugar().getQuantity();
}
Ora sembra che vada tutto bene. Ma quando si scrive codice Java, è meglio evitare di implementare controlli null . Vediamo come è possibile farlo utilizzando Opzionale.

Come creare Opzionale

Esistono tre modi per creare oggetti opzionali:
  • of(valore T) — istanziazione di un oggetto facoltativo non nullo. Tieni presente che l'uso di of() per fare riferimento a un oggetto null genererà una NullPointerException .

  • ofNullable(valore T) : crea un valore opzionale per un oggetto che può essere null.

  • vuoto() - Crea un'istanza opzionale che rappresenta un riferimento a null .

// пример использования Optional.of(T Value)
String name = "foo";
Optional<String> stringExample = Optional.of(name)
// пример использования Optional.ofNullable(T Value)
Integer age = null;
Optional<Integer> integerExample= Optional.ofNullable(age)
// пример использования Optional.empty()
Optional<Object> emptyExample = Optional.empty();
Quindi hai un oggetto opzionale. Ora diamo un'occhiata ai due metodi principali per Opzionale:
  • isPresent() : questo metodo indica se l'oggetto opzionale contiene un valore non nullo.

  • get() : recupera il valore per Opzionale con il valore corrente. Tieni presente che chiamare get() su un Opzionale vuoto risulterà in una NullPointerException .

Tieni presente che se usi solo get() e isPresent() quando lavori con Opzionale, ti stai perdendo! Per capirlo, riscriviamo ora l'esempio precedente con Opzionale.

Miglioramento del controllo null con facoltativo

Allora come possiamo migliorare il codice sopra? Con Optional possiamo comprendere la presenza di un oggetto utilizzando isPresent() e recuperarlo utilizzando get() . Iniziamo impacchettando il risultato di coffee.getSugar() con Optional e utilizzando il metodo isPresent() . Questo ci aiuterà a determinare se getSugar() restituisce null.
Coffee coffee = new Coffee();
Optional<String> sugar = Optional.ofNullable(coffee.getSugar());
int quantity = 0;
if (sugar.isPresent()) {
  Sugar sugar = sugar.get();
  int quantity = sugar.getQuantity();
}
Guardando questo esempio, impacchettare il risultato di coffee.getSugar() in Optional non sembra aggiungere alcun valore, ma piuttosto aggiunge problemi. Possiamo migliorare il risultato utilizzando quelle che considero le mie funzioni preferite della classe Opzionale:
  • map(Function<? super T,? extends U> mapper) - Mappa il valore contenuto in Opzionale alla funzione fornita. Se il parametro Opzionale è vuoto, map() restituirà Opzionale.empty() .

  • orElse(T other) è una versione “speciale” del metodo get() . Può ottenere il valore contenuto in Opzionale. Tuttavia, nel caso di un Optional vuoto, restituirà il valore passato al metodo orElse() .

Il metodo restituirà il valore contenuto nell'istanza opzionale. Ma se il parametro Opzionale è vuoto, ovvero non contiene alcun valore, allora orElse() restituirà il valore passato alla firma del metodo, noto come valore predefinito.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
    .map(it -> it.getQuantity())
    .orElse(0);
Questo è davvero fantastico, almeno penso di sì. Ora, se in caso di valore vuoto non vogliamo restituire il valore predefinito, allora dobbiamo lanciare qualche tipo di eccezione. orElseThrow(Supplier<? extends X>ExceptionSupplier) restituisce il valore contenuto nei parametri Opzionali o genera un'eccezione se l'Opzionale è vuoto.
Coffee coffee = new Coffee();

Integer quantity = Optional.ofNullable(coffee.getSugar())
  .map(it -> it.getQuantity())
  .orElseThrow(IllegalArgumentException::new);
Come puoi vedere, l'opzione opzionale offre diversi vantaggi:
  • astrae i controlli nulli
  • fornisce un'API per la gestione di oggetti null
  • consente all'approccio dichiarativo di esprimere ciò che si sta ottenendo

Come diventare efficaci con gli Opzionali

Nel mio lavoro utilizzo Opzionale come tipo restituito quando un metodo può restituire uno stato "nessun risultato". Di solito lo uso quando definisco i tipi restituiti per i metodi.
Optional<Coffee> findByName(String name) {
   ...
}
A volte questo non è necessario. Ad esempio, se ho un metodo che restituisce un int , come getQuantity() nella classe Sugar , allora il metodo potrebbe restituire 0 se il risultato è null per rappresentare "nessuna quantità". Ora, sapendo questo, possiamo pensare che il parametro Sugar nella classe Coffee possa essere rappresentato come Opzionale. A prima vista sembra una buona idea perché, in teoria, non è necessario che lo zucchero sia presente nel caffè. Tuttavia, è qui che vorrei affrontare quando non utilizzare Opzionale. Dovremmo evitare di utilizzare Opzionale nei seguenti scenari:
  • Come tipi di parametri per POJO , come DTO . Gli facoltativi non sono serializzabili, quindi utilizzarli in un POJO rende l'oggetto non serializzabile.

  • Come argomento di metodo. Se l'argomento di un metodo può essere null , dal punto di vista del puro codice, passare null è comunque preferibile rispetto a passare Optional. Inoltre, puoi creare metodi di sovraccarico per gestire in modo astratto l'assenza di un argomento del metodo null.

  • Per rappresentare un oggetto Collection mancante. Le raccolte possono essere vuote, quindi una Collection vuota , come un Set o una List vuota , deve essere utilizzata per rappresentare una Collection senza valori.

Conclusione

L'opzionale è diventato una potente aggiunta alla libreria Java. Fornisce un modo per gestire oggetti che potrebbero non esistere. Pertanto, se ne dovrebbe tenere conto nello sviluppo di metodi senza cadere nella trappola dell’abuso. Sì, puoi scrivere un ottimo codice che implementa controlli nulli e gestione nulli, ma la comunità Java preferisce utilizzare Opzionale. Comunica in modo efficace come gestire i valori mancanti, è molto più facile da leggere rispetto ai disordinati controlli Null e, a lungo termine, provoca meno bug nel codice.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION