5

Haben Sie eine schöne Alternative zu Apache Commons Validate oder Guava Preconditions wissen, dass Illegal statt Nullpointer werfen würde, wenn geprüft wird, ob Objekt nicht null (außer Spring Assert) ist?Voraussetzungen Bibliothek Illegal werfen für NotNull zu überprüfen


Ich bin mir bewusst, dass Javadocs sagen:

Anwendungen Instanzen dieser Klasse werfen sollte [Nullpointer] andere illegale Verwendungen des Null-Objekt anzuzeigen.

Trotzdem mag ich es einfach nicht. Für mich bedeutete NPE immer, dass ich einfach vergessen habe, irgendwo NULL-Referenzen zu bekommen. Meine Augen sind so trainiert, dass ich Logs mit einer Geschwindigkeit von wenigen Seiten pro Sekunde sehen kann und wenn ich das tue, ist immer ein Bugalarm in meinem Kopf aktiviert. Daher wäre es ziemlich verwirrend für mich, dass es dort geworfen wird, wo ich eine IllegalArgumentException erwarte.

Sagen, ich habe eine Bohne:

public class Person { 
    private String name; 
    private String phone; 
    //.... 
} 

und eine Service-Methode:

public void call(Person person) { 
    //assert person.getPhone() != null 
    //.... 
} 

In einem bestimmten Kontext es in Ordnung sein kann, dass eine Person kein Telefon hat (meine Oma nicht besitzt irgendein). Aber wenn Sie solche Person anrufen möchten, ruft es für mich die Anruf Methode mit einem IllegalArgument übergeben. Schauen Sie sich die Hierarchie an - NullPointerException ist nicht einmal eine Unterklasse von IllegalArgumentException. Es sagt Ihnen im Grunde - Wieder haben Sie versucht, einen Getter auf null Referenz aufzurufen.

Außerdem gab es bereits Diskussionen und es gibt this nette Antwort, die ich voll und ganz unterstütze. Also meine Frage ist nur - brauche ich so hässliche Dinge zu tun:

Validate.isTrue(person.getPhone() != null, "Can't call a person that hasn't got a phone"); 

es auf meine Art zu haben, oder gibt es eine Bibliothek, die nur Illegal für eine NotNull Check werfen würde?

+4

Nicht klar, was Sie unter "eine korrekt behandelte Situation" verstehen. Sicher, es handelt sich nicht um eine zufällige Dereferenzierung von 'null', sondern um dasselbe: Eine Methode wird aufgerufen, wobei 'null' für einen Parameter übergeben wird, der nicht 'null' sein kann, was genauso viel wie ein Programmierfehler ist . – ColinD

+0

sicher, aber in diesem Fall NPE (in meiner Interpretation) behandelt wird, wird die IllegalArgumentException nicht behandelt. Und tatsächlich ist es normalerweise von einigen Servlet-Ebenen Ausnahme-Handler oder SMS. – macias

+1

FWIW, das JDK legt einen ziemlich festen Präzedenzfall fest, dass * es * damit rechnet, dass ungültige Nullen behandelt werden. –

Antwort

4

Da das Thema dieser Frage in „Die richtige Verwendung von Illegal und Nullpointer“ entwickelt hat, möchte ich die Straße nach vorn Antwort in Effective Java Artikel darauf hinzuweisen, 60 (zweite Ausgabe):

Diskutierbar Alle fehlerhaften Methodenaufrufe laufen auf ein unzulässiges Argument oder einen illegalen Zustand hinaus, aber andere Ausnahmen werden standardmäßig für bestimmte Arten von ungültigen Argumenten und Zuständen verwendet. Wenn ein Aufrufer Null in einem Parameter übergibt, für den Nullwerte nicht zulässig sind, schreibt Convention vor, dass NullPointerException anstelle von IllegalArgumentException ausgelöst wird.Wenn ein Aufrufer einen ungültigen Wert in einem Parameter übergibt, der einen Index in einer Sequenz darstellt, sollte IndexOutOfBoundsException eher als IllegalArgumentException ausgelöst werden.

-1

Sie können dies ganz einfach:

if (person.getPhone() == null) { 
    throw new IllegalArgumentException("Can't call a person that hasn't got a phone"); 
} 

an andere Programmierer klar ist, was Sie meinen, und genau das tut, was Sie wollen.

+0

huh, das ist noch hässlicher :) Mein "hässliches" Beispiel macht auch was ich will und es ist auch klar. Meine Frage war über eine Bibliothek, die IllegalArgumentException anstelle von NPE (wie Guava und Apache-Commons) für einen NotNull-Check auslöst. – macias

+0

Eigentlich ist dies der normale Weg, Parameter in Java zu überprüfen, und es hängt nicht von irgendeiner Bibliothek ab. Es gibt keinen Grund, das nicht zu benutzen, soweit ich das beurteilen kann. Außerdem kenne ich keine Kodierungsstil-Richtlinie, die besagt, dass dies hässlich ist. – Chronio

+0

Mein Stil Leitlinie sagt so;) Aber, im Ernst, ich tue auch oft wie Sie vorschlagen. Meine Frage ist nur etwas anderes. Das Ziel wäre eine kurze, saubere Überprüfung wie Validate.notNull (person.getPhone(), "msg"); – macias

3

Was ist mit Preconditions 's checkArgument?

public void call(Person person) { 
    Preconditions.checkArgument(person.getPhone() != null); 
    // cally things... 
} 

checkArgumentthrowsIllegalArgumentException statt NullPointerException.

+0

Ja, Apache-Commons Validate.isTrue löst auch IllegalArgumentException, aber Validate.notNull wirft NPE zu meiner Enttäuschung. – macias

+0

'Preconditions.checkArgument (...! = Null);' ist vielleicht nicht das, was Sie suchen, aber es liest sich immer noch etwas besser * (meiner Meinung nach) * als 'Validate.isTrue (...! = Null) ; weil es klar ist, dass es mit Vorbedingungen und Argumenten aus den Namen zu tun hat. –

+1

nun ja, das ist wahrscheinlich besser.+1;) – macias

0

Nicht, dass mir bewusst ist. Ich würde einfach Ihr eigenes rollen, um das gewünschte Verhalten mit einem kurzen Aufruf zu erhalten, indem Sie die Implementierung von Guava nachahmen, aber den Ausnahmetyp anpassen.

class Preconditionz { 
    public static <T> T checkNotNull(T reference, Object errorMessage) { 
     if (reference == null) { 
      throw new IllegalArgumentException(String.valueOf(errorMessage)); 
     } 
     return reference; 
    } 
} 

Ich mag gehen und import static diese wirklich häufig verwendeten Methoden auch, so dass Sie sie super kurz nennen.

import static com.whatever.util.Preconditionz.checkNotNull; 

// ... 

public void call(Person person) { 
    checkNotNull(person, "person"); 
    checkNotNull(person.getPhone(), "person.phone"); 
    // ... 
} 

Abhängig von der Umgebung, können Sie es nennen checkNotNull2 so ist es einfacher, den Import über die automatische Vervollständigung in Ihrem IDE hinzuzufügen, oder lassen Sie es neben dem Standard checkNotNull verwenden.

0

Ich denke, ich habe hier wieder etwas gelernt, dank der großartigen Kommentare von Olivier Grégoire, Louis Wasserman, CollinD und Captain Man. Die Standards sind in der Regel ein starker und ausreichender Grund, da sie die normalen Programmiersprachen immer korrekt verstehen lassen, aber in diesem speziellen Fall hatte ich diesen kleinen Zweifel, dass diese Regel um NPE vielleicht nicht zu gut ist. Java ist eine alte Sprache und einige seiner Funktionen haben sich als etwas unglücklich erwiesen (ich möchte nicht falsch sagen, das ist vielleicht zu starke Beurteilung) - wie checked exceptions, obwohl Sie auch nicht zustimmen können. Jetzt denke ich, dass diese Zweifel behoben sind und ich soll:

  • eine Illegal werfen, wenn sie in dem besonderen Kontext kann ich sagen, warum der Nullwert falsch ist eher aus der Business-Perspektive. Zum Beispiel in der Service-Methode public void call(Person person) Ich weiß, was es für das System bedeutet, dass die Telefonnummer null ist.
  • Werfen Sie eine NullPointerException, wenn ich nur weiß, dass der Nullwert hier falsch ist und früher oder später eine NullPointerException verursachen wird, aber in dem bestimmten Kontext weiß ich nicht, was es aus der geschäftlichen Perspektive bedeutet. Das Beispiel wären unveränderbare Sammlungen von Guava. Wenn Sie ein solches erstellen und versuchen, ein Element mit einem Nullwert hinzuzufügen, wird eine NPE ausgelöst. Es versteht nicht, was dieser Wert für dich bedeutet, es ist zu allgemein, aber es weiß einfach, dass es hier falsch ist, also beschließt es dir das sofort, mit einer angemesseneren Nachricht, damit du das Problem besser erkennen kannst.

oben im Auge zu haben würde ich sagen, die beste Option, die Behauptung in dem public void call(Person person) Beispiel zu machen, ist wie Kapitän Man schlägt vor:

Preconditions.checkArgument(person.getPhone() != null, "msg"); 

prüft Argument ist ein guter Name für diese Methode - es ist klar, dass Ich überprüfe die Einhaltung von Geschäftsabschlüssen anhand des Arguments "Person" und es ist klar, dass ich IllegalArgumentException erwarte, wenn es fehlschlägt. Es ist ein besserer Name als die Validate.isTrue von Apache Commons. Validate.notNull oder Preconditions.checkNotNull sagen dagegen, dass ich nach einer Nullreferenz suche und ich erwarte tatsächlich die NPE.

So wäre die endgültige Antwort - es gibt keine solche nette Bibliothek und sollte nicht sein, da dies verwirrend sein würde. (Und Spring Assert sollte korrigiert werden).

1

Sie können valid4j mit hancrest-matchers verwenden (gefunden auf Maven Central als org.valid4j: valid4j). Die 'Validation' Klasse hat die Unterstützung für regelmäßige Überprüfung von Eingaben (dh erzielbaren Ausnahmen werfen):

import static org.valid4j.Validation.*; 

validate(argument, isValid(), otherwiseThrowing(InvalidException.class)); 

Links:

Auf einer Randnotiz: Diese Bibliothek unterstützt auch Pre- und Post-Conditions (wie etwa Assertions) und es ist möglich, bei Bedarf eine eigene angepasste globale Richtlinie zu registrieren :

import static org.valid4j.Assertive.*; 

require(x, greaterThan(0)); // throws RequireViolation extends AssertionError 
... 
ensure(r, notNullValue()); // throws EnsureViolation extends AssertionError 
Verwandte Themen