È meglio usare assert o IllegalArgumentException per i parametri del metodo richiesti?

79

In Java, che è più altamente raccomandato, e perché? Entrambi i tipi generano eccezioni, quindi a tale riguardo gestirli è lo stesso. assert è leggermente più breve, ma non sono sicuro di quanto importi.

public void doStuff(Object obj) {
    assert obj != null;
    ...
}

vs

public void doStuff(Object obj) {
    if (obj == null) {
        throw new IllegalArgumentException("object was null");
    }
    ...
}
    
posta Daenyth 27.02.2012 - 19:30
fonte

6 risposte

103

ATTENZIONE!

Le asserzioni vengono rimosse in fase di runtime a meno che tu non specifichi esplicitamente di " abilitare le asserzioni "durante la compilazione del codice. Le asserzioni Java non devono essere utilizzate nel codice di produzione e devono essere limitate ai metodi privati (vedi Eccezioni contro asserzioni ), dal momento che i metodi privati dovrebbero essere conosciuti e utilizzati solo dagli sviluppatori. Anche assert genererà AssertionError che estende Error non Exception , e che normalmente indica che c'è un errore molto anomalo (come "OutOfMemoryError" da cui è difficile recuperare, non è vero?) che non ci si aspetta che sia in grado di trattare.

Rimuovi il flag "enable assertions" e verifica con un debugger e vedrai che non eseguirai il passo sulla chiamata di lancio di IllegalArgumentException ... poiché questo codice non è stato compilato (di nuovo, quando "ea" viene rimosso )

È meglio usare la seconda costruzione per metodi pubblici / protetti, e se vuoi qualcosa che è fatto in una riga di codice, c'è almeno un modo che conosco. Io personalmente uso il Framework di Spring 's% co_de Classe% con alcuni metodi per il controllo degli argomenti e che genera "IllegalArgumentException" in caso di errore. Fondamentalmente, quello che fai è:

Assert.notNull(obj, "object was null");

... Che infatti eseguirà esattamente lo stesso codice che hai scritto nel tuo secondo esempio. Ci sono alcuni altri metodi utili come Assert , hasText in là.

Non mi piace scrivere più codice del necessario, quindi sono felice quando ridurrò il numero di righe scritte di 2 (2 righe > 1 riga): -)

    
risposta data 27.02.2012 - 19:43
fonte
41

Devi usare un'eccezione. L'utilizzo di un'asserzione sarebbe un uso improprio della funzionalità.

Le eccezioni non controllate sono progettate per rilevare errori di programmazione degli utenti della tua libreria, mentre le asserzioni sono progettate per rilevare errori nella tua logica . Questi sono problemi separati che non dovrebbero essere mescolati.

Ad esempio, un'asserzione

assert myConnection.isConnected();

significa "So che ogni percorso di codice che porta a questa asserzione assicura che myConnection sia connesso, se il codice sopra non è riuscito a ottenere una connessione valida, dovrebbe aver generato un'eccezione o un ritorno prima di raggiungere questo punto."

D'altra parte, un controllo

if (!myConnection.isConnected()) {
    throw new IllegalArgumentException("connection is not established");
}

significa che "Chiamare la mia libreria senza stabilire una connessione è un errore di programmazione".

    
risposta data 27.02.2012 - 20:09
fonte
9

Se stai scrivendo una funzione che non ammette null come valore di parametro valido, devi aggiungere l'annotazione @Nonnull alla firma e utilizzare Objects.requireNonNull per verificare se l'argomento è null e lanciare NullPointerException se lo è. L'annotazione @Nonnull è per la documentazione e in alcuni casi fornirà avvisi utili in fase di compilazione. Non impedisce che% co_de venga passato al runtime.

void doStuff(@Nonnull Object obj) {
    Objects.requireNonNull(obj, "obj must not be null");

    // do stuff...
}

Aggiornamento: l'annotazione null non fa parte della libreria standard Java. Esistono invece numerosi standard concorrenti da librerie di terze parti (vedere Quale annotazione @NotNull Java dovrei usare? ). Ciò non significa che sia una cattiva idea usarlo, solo che non è standard.

    
risposta data 10.10.2017 - 20:37
fonte
2

Preferisco sempre lanciare IllegalArgumentException sulle asserzioni.

Le asserzioni sono usate principalmente in JUnit o altri strumenti di test, per verificare / affermare i risultati dei test. Quindi potrebbe dare una falsa impressione agli altri sviluppatori che il tuo metodo è un metodo di prova.

Inoltre ha senso lanciare IllegalArgumentException quando un metodo ha superato un argomento illegale o inappropriato . Questo è più coerente con la convenzione Exception Handling seguita dagli sviluppatori Java.

    
risposta data 22.02.2013 - 12:53
fonte
1

IMO il secondo è leggermente migliore perché porta più informazioni e potrebbe essere ulteriormente esteso (ad esempio estendendo la classe delle eccezioni) per essere ancora più informativo, inoltre non usa un confronto negativo che è più facile da capire.

    
risposta data 27.02.2012 - 19:38
fonte
1

Non uso molto gli aser, ma approccio comune con Lombock @NonNull: link

Implementazione di Lombok:      import lombok.NonNull;

public class NonNullExample extends Something {
  private String name;

  public NonNullExample(@NonNull Person person) {
    super("Hello");
    this.name = person.getName();
  }
}

Versione Java:

 import lombok.NonNull;

public class NonNullExample extends Something {
  private String name;

  public NonNullExample(@NonNull Person person) {
    super("Hello");
    if (person == null) {
      throw new NullPointerException("person");
    }
    this.name = person.getName();
  }
}

Lombok è una libreria davvero carina che uso ovunque

    
risposta data 19.11.2017 - 20:45
fonte

Leggi altre domande sui tag