Perché si dovrebbe usare Objects.requireNonNull ()?


214

Ho notato che molti metodi Java 8 in Oracle JDK utilizzano Objects.requireNonNull(), che genera internamente NullPointerExceptionse l'oggetto specificato (argomento) lo è null.

public static <T> T requireNonNull(T obj) {
    if (obj == null)
        throw new NullPointerException();
    return obj;
}

Ma NullPointerExceptionverrà lanciato comunque se un nulloggetto viene sottoposto a dereferenziazione. Quindi, perché si dovrebbe fare questo controllo null extra e lanciare NullPointerException?

Una risposta ovvia (o beneficio) è che rende il codice più leggibile e sono d'accordo. Sono desideroso di conoscere qualsiasi altro motivo per l'utilizzo Objects.requireNonNull()all'inizio del metodo.




1
Questo approccio al controllo degli argomenti ti consente di imbrogliare quando scrivi i test unitari. Spring ha anche programmi di utilità del genere (vedi docs.spring.io/spring/docs/current/javadoc-api/org/… ). Se si dispone di un "if" e si desidera avere una copertura di test unitaria elevata, è necessario coprire entrambi i rami: quando la condizione è soddisfatta e quando la condizione non è soddisfatta. Se lo usi Objects.requireNonNull, il tuo codice non ha ramificazioni, quindi un singolo passaggio di un test unit ti darà una copertura del 100% :-)
xorcus

Risposte:


214

Perché puoi rendere esplicite le cose facendo così. Piace:

public class Foo {
  private final Bar bar;

  public Foo(Bar bar) {
    Objects.requireNonNull(bar, "bar must not be null");
    this.bar = bar;
  }

O più breve:

  this.bar = Objects.requireNonNull(bar, "bar must not be null");

Ora sai :

  • quando un oggetto Foo è stato creato con successo usandonew()
  • quindi il suo campo a barre è garantito non nullo.

Paragonalo a: crei un oggetto Foo oggi e domani invochi un metodo che usa quel campo e lancia. Molto probabilmente, non saprai domani perché quel riferimento era nullo ieri quando è stato passato al costruttore!

In altre parole: usando esplicitamente questo metodo per controllare i riferimenti in arrivo è possibile controllare il momento in cui verrà generata l'eccezione. E la maggior parte delle volte, vuoi fallire il più velocemente possibile !

I principali vantaggi sono:

  • come detto, comportamento controllato
  • debug più semplice - perché si getta nel contesto della creazione dell'oggetto. In un momento in cui hai una certa possibilità che i tuoi registri / tracce ti dicano cosa è andato storto!
  • e come mostrato sopra: il vero potere di questa idea si sviluppa in congiunzione con i campi finali . Perché ora qualsiasi altro codice nella tua classe può tranquillamente presumere che barnon sia null - e quindi non hai bisogno di alcun if (bar == null)controllo in altri posti!

23
Puoi rendere il tuo codice più compatto scrivendothis.bar = Objects.requireNonNull(bar, "bar must not be null");
Kirill Rakhman il

3
@KirillRakhman Insegnare a GhostCat qualcosa di interessante che non sapevo -> vincere un biglietto nella lotteria di votazione di GhostCat.
GhostCat,

1
Penso che il commento n. 1 qui sia il vero vantaggio di Objects.requireNonNull(bar, "bar must not be null");. Grazie per questo
Kawu,

1
Quale è stato il primo, e perché le persone "in lingua" dovrebbero seguire gli autori di alcune biblioteche ?! Perché la guava non segue il comportamento del lang Java ?!
GhostCat,

1
Il this.bar = Objects.requireNonNull(bar, "bar must not be null");è ok nei costruttori, ma potenzialmente pericolosa in altri metodi se due o più variabili sono impostate nello stesso metodo. Esempio: talkwards.com/2018/11/03/…
Erk,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.