it-swarm.com.de

Vermeiden von! = Null-Anweisungen

Ich verwende object != null häufig, um NullPointerException zu vermeiden.

Gibt es eine gute Alternative dazu? 

Zum Beispiel:

if (someobject != null) {
    someobject.doCalc();
}

Dies vermeidet eine NullPointerException, wenn es unbekannt ist, ob das Objekt null ist oder nicht.

Beachten Sie, dass die akzeptierte Antwort möglicherweise nicht mehr aktuell ist, siehe https://stackoverflow.com/a/2386013/12943 für einen neueren Ansatz.

3729
Goran Martinic

Das klingt für mich wie ein ziemlich allgemeines Problem, mit dem sich Junior- und Intermediate-Entwickler zu einem bestimmten Zeitpunkt konfrontiert sehen: Sie kennen die Verträge, an denen sie beteiligt sind, nicht oder vertrauen ihnen nicht, und sie prüfen defensiv ihre Nullwerte. Wenn sie ihren eigenen Code schreiben, neigen sie dazu, NULL-Werte zurückzugeben, um etwas anzuzeigen, wodurch der Anrufer nach NULL-Werten suchen muss.

Anders ausgedrückt: Es gibt zwei Fälle, in denen die Nullprüfung auftritt:

  1. Null ist eine gültige Antwort im Sinne des Vertrags; und

  2. Wo es keine gültige Antwort ist.

(2) ist einfach. Verwenden Sie entweder assert-Anweisungen (Assertions) oder erlauben Sie Fehler (z. B. NullPointerException ). Assertionen sind eine stark unterbenutzte Java-Funktion, die in 1.4 hinzugefügt wurde. Die Syntax lautet:

assert <condition>

oder

assert <condition> : <object>

dabei ist <condition> ein boolescher Ausdruck und <object> ein Objekt, dessen Ausgabe der toString()-Methode in den Fehler aufgenommen wird.

Eine assert-Anweisung löst eine Error (AssertionError) aus, wenn die Bedingung nicht erfüllt ist. Standardmäßig ignoriert Java Assertions. Sie können Zusicherungen aktivieren, indem Sie die Option -ea an die JVM übergeben. Sie können Assertions für einzelne Klassen und Pakete aktivieren und deaktivieren. Dies bedeutet, dass Sie den Code während der Entwicklung und des Tests mit den Assertions validieren und in einer Produktionsumgebung deaktivieren können, obwohl meine Tests kaum Auswirkungen auf die Performance von Assertions gezeigt haben.

Das Verwenden von Assertions ist in diesem Fall nicht zulässig, da der Code einfach fehlschlägt. Dies ist der Fall, wenn Sie Assertions verwenden. Der einzige Unterschied besteht darin, dass es mit Behauptungen früher, sinnvoller und möglicherweise mit zusätzlichen Informationen geschehen kann, was Ihnen helfen kann, herauszufinden, warum es passiert, wenn Sie es nicht erwartet hätten.

(1) ist etwas schwieriger. Wenn Sie den Code, den Sie anrufen, nicht kontrollieren können, stecken Sie fest. Wenn null eine gültige Antwort ist, müssen Sie danach suchen.

Wenn es sich jedoch um Code handelt, den Sie kontrollieren (und dies ist häufig der Fall), ist es eine andere Geschichte. Vermeiden Sie die Verwendung von Nullen als Antwort. Mit Methoden, die Sammlungen zurückgeben, ist es ganz einfach: Leere Sammlungen (oder Arrays) anstelle von Nullen werden fast immer zurückgegeben.

Bei Nicht-Sammlungen könnte es schwieriger sein. Betrachten Sie dies als Beispiel: Wenn Sie über folgende Schnittstellen verfügen:

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

parser nimmt rohe Benutzereingaben entgegen und findet etwas zu tun, wenn Sie beispielsweise eine Befehlszeilenschnittstelle für etwas implementieren. Jetzt können Sie den Vertrag so einstellen, dass er null zurückgibt, wenn es keine geeignete Aktion gibt. Das führt zur Nullprüfung, über die Sie sprechen.

Eine alternative Lösung ist, niemals null zurückzugeben und stattdessen das Muster Null Object zu verwenden:

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

Vergleichen Sie:

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

zu

ParserFactory.getParser().findAction(someInput).doSomething();

dies ist ein viel besseres Design, da es zu prägnanterem Code führt.

Vielleicht ist es jedoch durchaus angebracht, dass die findAction () - Methode eine Exception mit einer aussagekräftigen Fehlermeldung auslöst - insbesondere in diesem Fall, wenn Sie auf Benutzereingaben angewiesen sind. Es wäre viel besser für die findAction-Methode, eine Exception auszulösen, als für die aufrufende Methode, mit einer einfachen NullPointerException ohne Erklärung zu explodieren.

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

Oder wenn Sie denken, dass der Try/Catch-Mechanismus zu hässlich ist, anstatt Do Nothing. Ihre Standardaktion sollte dem Benutzer eine Rückmeldung geben.

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}
2487
cletus

Wenn Sie Java IDE wie JetBrains IntelliJ IDEA , Eclipse oder Netbeans oder ein Tool wie findbugs verwenden (oder dies planen), können Sie Anmerkungen verwenden um dieses Problem zu lösen.

Grundsätzlich haben Sie @Nullable und @NotNull.

Sie können in Methoden und Parametern wie folgt verwenden:

@NotNull public static String helloWorld() {
    return "Hello World";
}

oder

@Nullable public static String helloWorld() {
    return "Hello World";
}

Das zweite Beispiel wird nicht kompiliert (in IntelliJ IDEA).

Wenn Sie die erste helloWorld()-Funktion in einem anderen Code verwenden:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

Nun sagt Ihnen der IntelliJ IDEA Compiler, dass die Prüfung unbrauchbar ist, da die helloWorld()-Funktion niemals null zurückgibt.

Parameter verwenden

void someMethod(@NotNull someParameter) { }

wenn du so etwas schreibst:

someMethod(null);

Das wird nicht kompiliert.

Letztes Beispiel mit @Nullable

@Nullable iWantToDestroyEverything() { return null; }

Dies tun

iWantToDestroyEverything().something();

Und Sie können sicher sein, dass dies nicht passieren wird. :)

Es ist eine nette Möglichkeit, den Compiler etwas mehr als üblich prüfen zu lassen und Ihre Verträge stärker durchzusetzen. Leider wird es nicht von allen Compilern unterstützt.

In IntelliJ IDEA 10.5 und neuer wurde Unterstützung für alle anderen @Nullable@NotNull-Implementierungen hinzugefügt.

Siehe Blogbeitrag Flexibler und konfigurierbar @ Nullable/@ NotNull-Anmerkungen.

559
Luca Molteni

Wenn Nullwerte nicht zulässig sind

Wenn Ihre Methode extern aufgerufen wird, beginnen Sie folgendermaßen:

public void method(Object object) {
  if (object == null) {
    throw new IllegalArgumentException("...");
  }

In der restlichen Methode wissen Sie dann, dass object nicht null ist.

Wenn es sich um eine interne Methode (nicht Teil einer API) handelt, dokumentieren Sie einfach, dass sie nicht null sein kann, und das ist es.

Beispiel:

public String getFirst3Chars(String text) {
  return text.subString(0, 3);
}

Wenn Ihre Methode jedoch nur den Wert weitergibt und die nächste Methode den Wert weitergibt, kann dies problematisch werden. In diesem Fall sollten Sie das Argument wie oben prüfen.

Wenn null erlaubt ist

Das hängt wirklich davon ab. Wenn ich finde, dass ich oft so etwas mache:

if (object == null) {
  // something
} else {
  // something else
}

Also verzweige ich und mache zwei völlig verschiedene Dinge. Es gibt kein hässliches Code-Snippet, da ich abhängig von den Daten zwei verschiedene Dinge tun muss. Soll ich zum Beispiel an der Eingabe arbeiten oder einen guten Standardwert berechnen?


Es ist eigentlich selten für mich, die Redewendung "if (object != null && ..." zu verwenden.

Es kann einfacher sein, Ihnen Beispiele zu geben, wenn Sie Beispiele zeigen, wo Sie normalerweise das Idiom verwenden.

296
myplacedk

Wow, ich hasse es fast, eine weitere Antwort hinzuzufügen, wenn wir 57 verschiedene Möglichkeiten haben, NullObject pattern zu empfehlen. Ich glaube jedoch, dass einige an dieser Frage interessierte Personen gerne wissen möchten, dass Java 7 einen Vorschlag für die Verwendung von "null-sichere Handhabung" - eine optimierte Syntax für die if-not-gleich-null-Logik.

Das von Alex Miller gegebene Beispiel sieht folgendermaßen aus:

public String getPostcode(Person person) {  
  return person?.getAddress()?.getPostcode();  
}  

?. bedeutet, dass der linke Bezeichner nur dann aufgehoben wird, wenn er nicht null ist. Andernfalls wird der Rest des Ausdrucks als null ausgewertet. Einige Leute wie das Java Posse-Mitglied Dick Wall und die Wähler bei Devoxx lieben diesen Vorschlag wirklich, aber es gibt auch Widerstand, da er die Verwendung von null als Wächterwert ermutigen wird.


Update: Ein offizieller Vorschlag für einen nullsicheren Operator in Java 7 wurde unter Project Coin. Übergeben. Die Syntax unterscheidet sich ein wenig von dem obigen Beispiel, aber es ist die gleiche Vorstellung.


Update: Der Vorschlag für einen nullsicheren Operator wurde nicht in die Projektmünze aufgenommen. Daher wird diese Syntax in Java 7 nicht angezeigt.

222
erickson

Wenn undefinierte Werte nicht zulässig sind:

Sie können Ihre IDE so konfigurieren, dass Sie vor einer möglichen Null-Dereferenzierung gewarnt werden. Z.B. In Eclipse siehe Preferences> Java> Compiler> Fehler/Warnungen/Nullanalyse.

Wenn undefinierte Werte zulässig sind:

Wenn Sie eine neue API definieren möchten, für die undefinierte Werte sinnvoll sind, verwenden Sie das Optionsmuster (ist möglicherweise aus funktionalen Sprachen bekannt). Es hat folgende Vorteile:

  • In der API wird explizit angegeben, ob eine Eingabe oder eine Ausgabe vorhanden ist oder nicht.
  • Der Compiler zwingt Sie, den "undefinierten" Fall zu behandeln.
  • Option ist eine Monade , so dass keine ausführliche Nullprüfung erforderlich ist. Verwenden Sie einfach map/foreach/getOrElse oder einen ähnlichen Kombinator, um den Wert (Beispiel) sicher zu verwenden.

Java 8 hat eine eingebaute Optional -Klasse (empfohlen); Für frühere Versionen gibt es Bibliotheksalternativen, zum Beispiel Guava s Optional oder FunctionalJava s Option . Wie bei vielen Mustern im funktionalen Stil führt die Verwendung von Option in Java (sogar 8) zu einer gewissen Anzahl von Boilerplates, die Sie mit einer weniger ausführlichen JVM-Sprache reduzieren können, z. Scala oder Xtend.

Wenn Sie sich mit einer API befassen müssen, die möglicherweise Nullen zurückgibt, können Sie in Java nicht viel tun. Xtend und Groovy verfügen über den Elvis-Operator?: und den nullsicheren Dereferenzierungsoperator?.. Beachten Sie jedoch, dass dies bei einer NULL-Referenz den Wert null zurückgibt Umgang mit Null.

184
thSoft

Nur für diese Situation -

Es wird nicht geprüft, ob eine Variable vor dem Aufruf einer equals-Methode null ist (ein Beispiel zum Vergleich von Zeichenfolgen)

if ( foo.equals("bar") ) {
 // ...
}

führt zu einer NullPointerException, falls foo nicht existiert.

Sie können dies vermeiden, wenn Sie Ihre Strings wie folgt vergleichen:

if ( "bar".equals(foo) ) {
 // ...
}
169
echox

Mit Java 8 kommt die neue Java.util.Optional-Klasse, die einige der Probleme löst. Man kann zumindest sagen, dass es die Lesbarkeit des Codes verbessert und im Falle von öffentlichen APIs den Vertrag der API für den Client-Entwickler klarer macht.

Sie arbeiten so:

Ein optionales Objekt für einen gegebenen Typ (Fruit) wird als Rückgabetyp einer Methode erstellt. Es kann leer sein oder ein Fruit-Objekt enthalten:

public static Optional<Fruit> find(String name, List<Fruit> fruits) {
   for (Fruit fruit : fruits) {
      if (fruit.getName().equals(name)) {
         return Optional.of(fruit);
      }
   }
   return Optional.empty();
}

Sehen Sie sich nun diesen Code an, in dem wir eine Liste von Fruit (fruits) für eine bestimmte Fruit-Instanz durchsuchen:

Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
   Fruit fruit = found.get();
   String name = fruit.getName();
}

Mit dem Operator map() können Sie eine Berechnung an einem optionalen Objekt durchführen oder einen Wert daraus extrahieren. Mit orElse() können Sie einen Fallback für fehlende Werte bereitstellen.

String nameOrNull = find("lemon", fruits)
    .map(f -> f.getName())
    .orElse("empty-name");

Natürlich ist die Überprüfung auf null/leere Werte immer noch notwendig, aber zumindest ist sich der Entwickler bewusst, dass der Wert leer sein kann und das Risiko des Vergessens der Überprüfung begrenzt ist.

In einer von Grund auf erstellten API, die Optional verwendet, wenn ein Rückgabewert leer ist und nur ein einfaches Objekt zurückgibt, wenn es nicht null (Konvention) sein kann, kann der Clientcode die Überprüfung von einfachen Objektrückgabewerten auf Null zurücksetzen.

Natürlich könnte Optional auch als Methodenargument verwendet werden. In einigen Fällen ist dies eine bessere Möglichkeit, optionale Argumente als 5 oder 10 Überladungsmethoden anzugeben.

Optional bietet andere praktische Methoden an, z. B. orElse, die die Verwendung eines Standardwerts ermöglichen, und ifPresent, die mit Lambda-Ausdrücken funktioniert.

Ich lade Sie ein, diesen Artikel (meine Hauptquelle für das Schreiben dieser Antwort) zu lesen, in dem sowohl die NullPointerException (und allgemein der Nullzeiger) als auch die (teilweise) Lösung, die von Optional eingebracht wird, gut erklärt werden: Java Optionale Objekte.

148
Pierre Henry

Je nachdem, welche Art von Objekten Sie überprüfen, können Sie möglicherweise einige der Klassen in den Apache-Commons verwenden, z. B .: Apache commons lang und Apache commons collections

Beispiel:

String foo;
...
if( StringUtils.isBlank( foo ) ) {
   ///do something
}

oder (je nachdem, was Sie überprüfen müssen):

String foo;
...
if( StringUtils.isEmpty( foo ) ) {
   ///do something
}

Die StringUtils-Klasse ist nur eine von vielen. Es gibt einige gute Klassen in den Commons, die null sichere Manipulationen durchführen.

Hier folgt ein Beispiel, wie Sie Null-Vallidation in Java verwenden können, wenn Sie die Apache-Bibliothek (commons-lang-2.4.jar) einbinden.

public DOCUMENT read(String xml, ValidationEventHandler validationEventHandler) {
    Validate.notNull(validationEventHandler,"ValidationHandler not Injected");
    return read(new StringReader(xml), true, validationEventHandler);
}

Und wenn Sie Spring verwenden, hat Spring auch die gleiche Funktionalität in seinem Paket, siehe Bibliothek (spring-2.4.6.jar).

Beispiel zur Verwendung dieser statischen Klasse von spring (org.springframework.util.Assert)

Assert.notNull(validationEventHandler,"ValidationHandler not Injected");
121
javamonkey79
  • Wenn Sie der Meinung sind, dass ein Objekt nicht null sein sollte (oder ein Fehler ist), verwenden Sie eine Bestätigung.
  • Wenn Ihre Methode keine Nullparameter akzeptiert, sagen Sie es im Javadoc und verwenden Sie eine Assert-Anweisung.

Sie müssen nur auf object! = Null prüfen, wenn Sie den Fall behandeln möchten, in dem das Objekt null sein kann.

Es gibt einen Vorschlag, neue Anmerkungen in Java7 hinzuzufügen, um mit null/notnull-Parametern zu helfen: http://tech.puredanger.com/Java7/#jsr308

91
pgras

Ich bin ein Fan von "Fail-Fast" Code. Fragen Sie sich selbst - tun Sie etwas Nützliches, wenn der Parameter null ist? Wenn Sie keine klare Antwort darauf haben, was Ihr Code in diesem Fall tun soll ... Er sollte niemals anfangs null sein, dann ignorieren Sie ihn und erlauben Sie das Auslösen einer NullPointerException. Der aufrufende Code macht eine NPE genauso verständlich wie eine IllegalArgumentException, aber es ist für den Entwickler einfacher zu debuggen und zu verstehen, was schiefgegangen ist, wenn eine NPE ausgelöst wird, anstatt dass Ihr Code versucht, eine andere unerwartete Kontingenz auszuführen Logik - was letztendlich dazu führt, dass die Anwendung trotzdem ausfällt. 

85
Alex Worden

Das Google Collections-Framework bietet eine gute und elegante Möglichkeit, die Nullprüfung durchzuführen.

Es gibt eine Methode in einer Bibliotheksklasse wie folgt:

static <T> T checkNotNull(T e) {
   if (e == null) {
      throw new NullPointerException();
   }
   return e;
}

Und die Verwendung ist (mit import static):

...
void foo(int a, Person p) {
   if (checkNotNull(p).getAge() > a) {
      ...
   }
   else {
      ...
   }
}
...

Oder in deinem Beispiel:

checkNotNull(someobject).doCalc();
72
user2427

Manchmal verfügen Sie über Methoden, die mit seinen Parametern arbeiten, die eine symmetrische Operation definieren:

a.f(b); <-> b.f(a);

Wenn Sie wissen, dass b niemals Null sein kann, können Sie es einfach austauschen. Es ist am nützlichsten für Gleichgestellte: Anstelle von foo.equals("bar"); sollten Sie "bar".equals(foo); besser tun.

Anstelle des Null-Objekt-Musters - das hat seine Verwendung - könnten Sie Situationen in Betracht ziehen, in denen das Null-Objekt ein Fehler ist.

Wenn die Ausnahme ausgelöst wird, überprüfen Sie die Stapelablaufverfolgung und arbeiten Sie den Fehler durch.

69
Jim Nelson

Null ist kein 'Problem'. Es ist ein integraler Bestandteil eines vollständigen Modellierungswerkzeugsatzes. Software zielt darauf ab, die Komplexität der Welt zu modellieren, und null trägt die Last. Null gibt "Keine Daten" oder "Unbekannt" in Java und dergleichen an. Daher ist es angebracht, für diese Zwecke Nullen zu verwenden. Ich bevorzuge nicht das Muster "Nullobjekt". Ich denke, es wirft das ' wer wird die Wächter beschützen ' Problem auf.
Wenn du mich fragst, wie meine Freundin heißt, sage ich dir, dass ich keine Freundin habe. In der Sprache Java gebe ich null zurück. Eine Alternative wäre, eine sinnvolle Ausnahme auszulösen, um auf ein Problem hinzuweisen, das nicht direkt dort gelöst werden kann (oder will), und es irgendwo weiter oben im Stapel zu delegieren, um erneut einen Datenzugriffsfehler zu versuchen oder dem Benutzer zu melden.

  1. Geben Sie für eine "unbekannte Frage" eine "unbekannte Antwort" an. (Seien Sie nullsicher, wenn dies aus geschäftlicher Sicht korrekt ist.) Überprüfen Sie die Argumente einmal auf Null Durch die Verwendung einer Methode vor der Verwendung werden mehrere Anrufer vor einem Anruf von der Überprüfung entlastet.

    public Photo getPhotoOfThePerson(Person person) {
        if (person == null)
            return null;
        // Grabbing some resources or intensive calculation
        // using person object anyhow.
    }
    

    Vorherige führt zu einem normalen logischen Ablauf, um kein Foto einer nicht existierenden Freundin aus meiner Fotobibliothek zu erhalten.

    getPhotoOfThePerson(me.getGirlfriend())
    

    Und es passt zur neuen Java API (mit Blick auf die Zukunft)

    getPhotoByName(me.getGirlfriend()?.getName())
    

    Während es eher "normaler Geschäftsfluss" ist, für einige Personen kein in der Datenbank gespeichertes Foto zu finden, habe ich für einige andere Fälle Paare wie unten verwendet

    public static MyEnum parseMyEnum(String value); // throws IllegalArgumentException
    public static MyEnum parseMyEnumOrNull(String value);
    

    Und nicht ungern <alt> + <shift> + <j> eingeben (Javadoc in Eclipse generieren) und drei zusätzliche Wörter für Ihre öffentliche API schreiben. Dies ist mehr als genug für alle, außer für diejenigen, die keine Dokumentation lesen.

    /**
     * @return photo or null
     */
    

    oder

    /**
     * @return photo, never null
     */
    
  2. Dies ist ein eher theoretischer Fall und in den meisten Fällen sollten Sie Java null safe API bevorzugen (falls es in weiteren 10 Jahren veröffentlicht wird), aber NullPointerException ist eine Unterklasse eines Exception. Somit ist es eine Form von Throwable, die Bedingungen angibt, die eine vernünftige Anwendung abfangen möchte ( javadoc )! Um den ersten Vorteil von Ausnahmen zu nutzen und Fehlerbehandlungscode von 'normalem' Code zu trennen ( gemäß den Erstellern von Java ), ist es für mich angebracht, NullPointerException zu fangen.

    public Photo getGirlfriendPhoto() {
        try {
            return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());
        } catch (NullPointerException e) {
            return null;
        }
    }
    

    Fragen könnten auftauchen:

    F. Was ist, wenn getPhotoDataSource() null zurückgibt?
    EIN. Es liegt an der Geschäftslogik. Wenn ich kein Fotoalbum finde, zeige ich Ihnen keine Fotos. Was ist, wenn appContext nicht initialisiert wird? Die Geschäftslogik dieser Methode lässt dies zu. Wenn dieselbe Logik strenger sein sollte als das Auslösen einer Ausnahme, ist sie Teil der Geschäftslogik, und es sollte eine explizite Prüfung auf Null durchgeführt werden (Fall 3). Die neue Java Null-sichere API eignet sich hier besser, um selektiv anzugeben, was impliziert und was nicht bedeutet, dass initialisiert werden muss , um fehlzuschlagen -Schnell bei Programmierfehlern.

    F: Redundanter Code könnte ausgeführt werden und unnötige Ressourcen könnten geholt werden.
    EIN. Dies könnte passieren, wenn getPhotoByName() versucht, eine Datenbankverbindung herzustellen, PreparedStatement zu erstellen und den Namen der Person zuletzt als SQL-Parameter zu verwenden. Der Ansatz für eine unbekannte Frage gibt eine unbekannte Antwort (Fall 1) funktioniert hier. Vor dem Abrufen von Ressourcen sollte die Methode die Parameter überprüfen und bei Bedarf ein "unbekanntes" Ergebnis zurückgeben.

    F. Dieser Ansatz hat eine Leistungsbeeinträchtigung aufgrund der Eröffnung des Versuchsabschlusses.
    EIN. Software sollte zunächst einfach zu verstehen und zu ändern sein. Erst danach konnte man über Leistung nachdenken, und zwar nur bei Bedarf! und wo benötigt! ( Quelle ) und viele andere).

    PS. Die Verwendung dieses Ansatzes ist genauso sinnvoll, wie die Verwendung des getrennten Fehlerbehandlungscodes vom - Prinzip des "regulären" Codes an einer bestimmten Stelle sinnvoll ist. Betrachten Sie das nächste Beispiel:

    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        try {
            Result1 result1 = performSomeCalculation(predicate);
            Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
            Result3 result3 = performThirdCalculation(result2.getSomeProperty());
            Result4 result4 = performLastCalculation(result3.getSomeProperty());
            return result4.getSomeProperty();
        } catch (NullPointerException e) {
            return null;
        }
    }
    
    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        SomeValue result = null;
        if (predicate != null) {
            Result1 result1 = performSomeCalculation(predicate);
            if (result1 != null && result1.getSomeProperty() != null) {
                Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
                if (result2 != null && result2.getSomeProperty() != null) {
                    Result3 result3 = performThirdCalculation(result2.getSomeProperty());
                    if (result3 != null && result3.getSomeProperty() != null) {
                        Result4 result4 = performLastCalculation(result3.getSomeProperty());
                        if (result4 != null) {
                            result = result4.getSomeProperty();
                        }
                    }
                }
            }
        }
        return result;
    }
    

    PPS. Für diejenigen, die schnell abstimmen (und die Dokumentation nicht so schnell lesen), möchte ich sagen, dass ich in meinem Leben noch nie eine Null-Zeiger-Ausnahme (NPE) festgestellt habe. Aber diese Möglichkeit wurde absichtlich von den Java Erstellern entworfen , da NPE eine Unterklasse von Exception ist. Wir haben einen Präzedenzfall in der Java -Historie, wenn ThreadDeath ein Error ist, nicht weil es sich tatsächlich um einen Anwendungsfehler handelt, sondern nur, weil er nicht zum Abfangen gedacht war! Wie viel NPE passt als Error als ThreadDeath! Aber es ist nicht.

  3. Nur dann auf "Keine Daten" prüfen, wenn dies von der Geschäftslogik impliziert wird.

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person != null) {
            person.setPhoneNumber(phoneNumber);
            dataSource.updatePerson(person);
        } else {
            Person = new Person(personId);
            person.setPhoneNumber(phoneNumber);
            dataSource.insertPerson(person);
        }
    }
    

    und

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person == null)
            throw new SomeReasonableUserException("What are you thinking about ???");
        person.setPhoneNumber(phoneNumber);
        dataSource.updatePerson(person);
    }
    

    Wenn appContext oder dataSource nicht initialisiert ist, bricht die nicht behandelte Laufzeit-NullPointerException den aktuellen Thread ab und wird von Thread.defaultUncaughtExceptionHandler (damit Sie Ihren bevorzugten Logger oder einen anderen Benachrichtigungsmechanismus definieren und verwenden können) verarbeitet. Wenn nicht gesetzt, druckt ThreadGroup # uncaughtException Stacktrace auf Systemfehler. Man sollte das Anwendungsfehlerprotokoll überwachen und das Jira-Problem für jede nicht behandelte Ausnahme öffnen, bei der es sich tatsächlich um einen Anwendungsfehler handelt. Der Programmierer sollte den Fehler irgendwo in der Initialisierung beheben.

68

Java 7 hat eine neue Java.util.Objects-Dienstprogrammklasse, für die es eine requireNonNull()-Methode gibt. Alles, was Sie tun, ist eine Variable NullPointerException, wenn das Argument null ist, aber der Code wird etwas aufgeräumt. Beispiel:

Objects.requireNonNull(someObject);
someObject.doCalc();

Die Methode ist am nützlichsten für testing unmittelbar vor einer Zuweisung in einem Konstruktor, wobei bei jeder Verwendung drei Codezeilen gespeichert werden können:

Parent(Child child) {
   if (child == null) {
      throw new NullPointerException("child");
   }
   this.child = child;
}

wird

Parent(Child child) {
   this.child = Objects.requireNonNull(child, "child");
}
66
Stuart Marks

Letztendlich ist die einzige Möglichkeit, dieses Problem vollständig zu lösen, die Verwendung einer anderen Programmiersprache:

  • In Objective-C können Sie das Äquivalent des Aufrufs einer Methode für nil ausführen, und es wird absolut nichts passieren. Dies macht die meisten Nullprüfungen überflüssig, kann jedoch die Diagnose von Fehlern erheblich erschweren.
  • In Nice , einer von Java abgeleiteten Sprache, gibt es zwei Versionen aller Typen: eine potentiell-null-Version und eine nicht-null-Version. Sie können Methoden nur für Nicht-Null-Typen aufrufen. Potentiell-Null-Typen können durch explizite Überprüfung auf Null in Nicht-Null-Typen konvertiert werden. Dies macht es viel einfacher zu wissen, wo Nullprüfungen notwendig sind und wo sie nicht sind.
48

Allgemeines "Problem" in der Tat in Java.

Zunächst meine Gedanken dazu:

Ich denke, dass es schlecht ist, etwas zu "essen", wenn NULL übergeben wurde, wenn NULL kein gültiger Wert ist. Wenn Sie die Methode nicht mit einem Fehler beenden, bedeutet dies, dass in Ihrer Methode nichts schiefgelaufen ist, was nicht der Fall ist. Dann geben Sie in diesem Fall wahrscheinlich Null zurück, und in der empfangenden Methode überprüfen Sie erneut nach Null, und es endet nie und Sie landen mit "if! = Null" usw.

IMHO, null muss ein kritischer Fehler sein, der die weitere Ausführung verhindert (dh, wenn null kein gültiger Wert ist).

So löse ich dieses Problem:

Zuerst folge ich dieser Konvention:

  1. Alle öffentlichen Methoden/API prüfen ihre Argumente immer auf null
  2. Alle privaten Methoden prüfen nicht auf Null, da es sich um kontrollierte Methoden handelt (lassen Sie sich einfach mit der Nullpointer-Ausnahme sterben, falls sie oben nicht behandelt wurde).
  3. Die einzigen anderen Methoden, die nicht auf Null prüfen, sind Dienstprogrammmethoden. Sie sind öffentlich, aber wenn Sie sie aus irgendeinem Grund anrufen, wissen Sie, welche Parameter Sie übergeben. Dies ist wie der Versuch, Wasser im Wasserkocher ohne Wasser zu kochen ...

Und schließlich lautet die erste Zeile der öffentlichen Methode im Code folgendermaßen:

ValidationUtils.getNullValidator().addParam(plans, "plans").addParam(persons, "persons").validate();

Beachten Sie, dass addParam () self zurückgibt, sodass Sie weitere Parameter zur Überprüfung hinzufügen können.

Die Methode validate() wirft die überprüfte ValidationException, wenn einer der Parameter null ist (aktiviert oder deaktiviert ist eher ein Design-/Geschmacksproblem, aber meine ValidationException ist markiert).

void validate() throws ValidationException;

Die Nachricht enthält den folgenden Text, wenn beispielsweise "plans" null ist:

" Ungültiger Argumentwert null für Parameter [plans] " gefunden

Wie Sie sehen, wird der zweite Wert in der addParam () - Methode (Zeichenfolge) für die Benutzermeldung benötigt, da Sie den übergebenen Variablennamen nicht ohne weiteres erkennen können, auch nicht mit Reflektion (sowieso nicht Gegenstand dieses Beitrags ...).

Und ja, wir wissen, dass wir jenseits dieser Linie keinen Wert mehr finden werden, also rufen wir einfach Methoden für diese Objekte auf.

Auf diese Weise ist der Code sauber, leicht zu pflegen und lesbar.

34
Oleg

Wenn Sie diese Frage stellen, weisen Sie darauf hin, dass Sie möglicherweise an Strategien zur Fehlerbehandlung interessiert sind. Der Architekt Ihres Teams sollte entscheiden, wie Fehler verarbeitet werden sollen. Dafür gibt es mehrere Möglichkeiten:

  1. lassen Sie die Exceptions durchlaufen - fangen Sie sie an der Hauptschleife oder in einer anderen Verwaltungsroutine.

    • Überprüfen Sie die Fehlerbedingungen und behandeln Sie sie entsprechend

Schauen Sie sich auch die aspektorientierte Programmierung an - sie haben die Möglichkeit, if( o == null ) handleNull() in Ihren Bytecode einzufügen.

32
xtofl

Zusätzlich zur Verwendung von assert können Sie Folgendes verwenden:

if (someobject == null) {
    // Handle null here then move on.
}

Das ist etwas besser als:

if (someobject != null) {
    .....
    .....



    .....
}
32
fastcodejava

Verwenden Sie einfach niemals null. Erlaube es nicht.

In meinen Klassen haben die meisten Felder und lokalen Variablen nicht-null-Standardwerte, und ich füge überall im Code Vertragsanweisungen (Always-On-Asserts) hinzu, um sicherzustellen, dass dies erzwungen wird (da dies prägnanter und ausdrucksvoller ist, als wenn man es zulässt.) als NPE auftauchen und dann die Zeilennummer auflösen müssen usw.).

Nachdem ich diese Praxis angenommen hatte, bemerkte ich, dass sich die Probleme scheinbar zu lösen schienen. Sie würden die Dinge viel früher im Entwicklungsprozess durch Zufall einfangen und erkennen, dass Sie eine Schwachstelle hatten ... und was noch wichtiger ist ... es hilft, die Bedenken der verschiedenen Module zu kapseln, verschiedene Module können sich gegenseitig "vertrauen" und keine Abfälle mehr Code mit if = null else Konstrukten!

Dies ist eine defensive Programmierung und führt auf lange Sicht zu deutlich saubererem Code. Bereinigen Sie die Daten immer, z. hier durch die Durchsetzung strenger Standards, und die Probleme gehen weg.

class C {
    private final MyType mustBeSet;
    public C(MyType mything) {
       mustBeSet=Contract.notNull(mything);
    }
   private String name = "<unknown>";
   public void setName(String s) {
      name = Contract.notNull(s);
   }
}


class Contract {
    public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; }
}

Die Verträge sind wie Mini-Unit-Tests, die immer laufen, auch in der Produktion, und wenn Dinge scheitern, wissen Sie warum, und nicht als zufällige NPE müssen Sie irgendwie herausfinden.

30
ianpojman

Guava, eine sehr nützliche Kernbibliothek von Google, verfügt über eine nette und nützliche API, um Nullen zu vermeiden. Ich finde UsingAndAvoidingNullExplained sehr hilfreich.

Wie im Wiki erklärt:

Optional<T> ist eine Möglichkeit, eine nullfähige T-Referenz durch eine .__ zu ersetzen. Nicht-Nullwert Ein Optional kann entweder eine Nicht-N-T-Referenz enthalten (In diesem Fall sagen wir, dass der Verweis "vorhanden" ist) oder er kann enthalten nichts (in diesem Fall sagen wir, die Referenz sei "nicht vorhanden"). Es ist niemals sagte zu "enthalten null".

Verwendungszweck:

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
28

Dies ist ein sehr häufiges Problem für jeden Java-Entwickler. Daher gibt es in Java 8 offizielle Unterstützung, um diese Probleme ohne überladenen Code zu beheben.

Java 8 hat Java.util.Optional<T> eingeführt. Es ist ein Container, der einen Wert ungleich Null enthalten kann oder nicht. Java 8 hat einen sichereren Weg für die Handhabung eines Objekts geschaffen, dessen Wert in einigen Fällen null sein kann. Es ist inspiriert von den Ideen von Haskell und Scala .

Kurz gesagt, die optionale Klasse enthält Methoden, um explizit mit den Fällen umzugehen, in denen ein Wert vorhanden ist oder nicht. Der Vorteil gegenüber Nullreferenzen besteht jedoch darin, dass Sie mit der optionalen Klasse <T> über den Fall nachdenken müssen, in dem der Wert nicht vorhanden ist. Folglich können Sie unbeabsichtigte Nullzeigerausnahmen verhindern.

In obigem Beispiel haben wir eine Heimservice-Fabrik, die einen Handle an mehrere in der Wohnung verfügbare Geräte zurückgibt. Diese Dienste sind jedoch möglicherweise nicht verfügbar/funktionsfähig. Dies bedeutet, dass es zu einer NullPointerException kommen kann. Anstatt vor der Verwendung eines Dienstes eine if-Bedingung mit dem Wert null hinzuzufügen, packen Sie ihn in Optional <Dienst> ein.

AUFNAHME ZUR OPTION <T>

Betrachten wir eine Methode, um eine Referenz einer Dienstleistung von einer Fabrik zu erhalten. Geben Sie die Dienstreferenz nicht zurück, sondern umschließen Sie sie mit Optional. Der API-Benutzer wird darauf hingewiesen, dass der zurückgegebene Dienst möglicherweise defekt ist oder nicht verfügbar/funktionsfähig ist

public Optional<Service> getRefrigertorControl() {
      Service s = new  RefrigeratorService();
       //...
      return Optional.ofNullable(s);
   }

Wie Sie sehen, bietet Optional.ofNullable() eine einfache Möglichkeit, die Referenz einzuwickeln. Es gibt andere Möglichkeiten, die Referenz von Optional zu erhalten, entweder Optional.empty() & Optional.of(). Eine für die Rückgabe eines leeren Objekts, anstatt null erneut abzustimmen, und die andere, um ein nicht-nullbares Objekt einzuwickeln.

WIE HILFT ES GENAU, NULL-CHECK ZU VERMEIDEN?

Wenn Sie ein Referenzobjekt umschlossen haben, bietet Optional viele nützliche Methoden zum Aufrufen von Methoden für eine umschlossene Referenz ohne NPE.

Optional ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);

Optional.ifPresent ruft den angegebenen Consumer mit einer Referenz auf, wenn es sich nicht um einen Nullwert handelt. Sonst tut es nichts.

@FunctionalInterface
public interface Consumer<T>

Stellt eine Operation dar, die ein einzelnes Eingabeargument akzeptiert und kein Ergebnis zurückgibt. Im Gegensatz zu den meisten anderen funktionalen Schnittstellen wird von Consumer erwartet, dass er über Nebeneffekte arbeitet .. _. Es ist so sauber und leicht verständlich. Im obigen Codebeispiel wird HomeService.switchOn(Service) aufgerufen, wenn der Verweis auf die Option Optional nicht null ist.

Wir verwenden den ternären Operator sehr häufig zum Überprüfen der Nullbedingung und geben einen alternativen Wert oder einen Standardwert zurück. Optional bietet eine andere Möglichkeit, dieselbe Bedingung zu behandeln, ohne NULL zu überprüfen. Optional.orElse (defaultObj) gibt defaultObj zurück, wenn das Optional einen Nullwert hat. Verwenden wir dies in unserem Beispielcode:

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

Jetzt macht HomeServices.get () dasselbe, aber auf eine bessere Art und Weise. Es wird geprüft, ob der Dienst bereits initialisiert ist oder nicht. Wenn dies der Fall ist, geben Sie dasselbe zurück oder erstellen Sie einen neuen neuen Dienst. Die optionale <T> .orElse (T) hilft dabei, einen Standardwert zurückzugeben.

Zum Schluss noch unser NPE-Code sowie null-Code ohne Check-In:

import Java.util.Optional;
public class HomeServices {
    private static final int NOW = 0;
    private static Optional<HomeServices> service;

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

public Optional<Service> getRefrigertorControl() {
    Service s = new  RefrigeratorService();
    //...
    return Optional.ofNullable(s);
}

public static void main(String[] args) {
    /* Get Home Services handle */
    Optional<HomeServices> homeServices = HomeServices.get();
    if(homeServices != null) {
        Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl();
        refrigertorControl.ifPresent(HomeServices::switchItOn);
    }
}

public static void switchItOn(Service s){
         //...
    }
}

Der vollständige Beitrag ist NPE sowie null-Check-freier Code… Wirklich?.

21
Yogesh Devatraj

Ich mag Artikel von Nat Pryce. Hier sind die Links:

In den Artikeln gibt es auch einen Link zu einem Git-Repository für einen Java-Dateityp, den ich interessant finde, aber ich denke nicht, dass dies alleine den. Nach einigen Recherchen im Internet denke ich, dass ! = Null Code Bloat hauptsächlich durch sorgfältiges Design verringert werden konnte.

20
Mr Palo

Ich habe das NullObjectPattern ausprobiert, aber für mich ist es nicht immer der beste Weg. Es gibt manchmal Situationen, in denen eine "keine Aktion" nicht angemessen ist.

NullPointerException ist eine Runtime-Ausnahme, die auf Fehler des Entwicklers hindeutet, und mit genügend Erfahrung sagt es Ihnen genau, wo der Fehler liegt.

Nun zur Antwort:

Versuchen Sie, alle Ihre Attribute und ihre Zugriffselemente so privat wie möglich zu machen, oder vermeiden Sie es, sie den Clients überhaupt zugänglich zu machen. Sie können die Argumentwerte natürlich im Konstruktor haben, aber durch die Reduzierung des Gültigkeitsbereichs lassen Sie nicht zu, dass die Client-Klasse einen ungültigen Wert übergibt. Wenn Sie die Werte ändern müssen, können Sie immer ein neues object erstellen. Sie überprüfen die Werte nur im Konstruktor einmal und in den übrigen Methoden können Sie fast sicher sein, dass die Werte nicht null sind.

Natürlich ist Erfahrung der bessere Weg, diesen Vorschlag zu verstehen und anzuwenden.

Byte!

18
OscarRyz

Die beste Alternative für Java 8 oder neuer ist die Verwendung der Optional -Klasse. 

Optional stringToUse = Optional.of("optional is there");
stringToUse.ifPresent(System.out::println);

Dies ist besonders praktisch für lange Ketten möglicher Nullwerte. Beispiel:

Optional<Integer> i = Optional.ofNullable(wsObject.getFoo())
    .map(f -> f.getBar())
    .map(b -> b.getBaz())
    .map(b -> b.getInt());

Beispiel zum Auslösen einer Ausnahme auf null:

Optional optionalCarNull = Optional.ofNullable(someNull);
optionalCarNull.orElseThrow(IllegalStateException::new);

In Java 7 wurde die Methode Objects.requireNonNull eingeführt, die hilfreich sein kann, wenn etwas auf Nicht-NULL-Wert geprüft werden soll. Beispiel:

String lowerVal = Objects.requireNonNull(someVar, "input cannot be null or empty").toLowerCase();
15
Raghu K Nair

Ich ignoriere die Antworten, die die Verwendung von Nullobjekten in jeder Situation suggerieren. Dieses Muster kann die Kontrakte brechen und Probleme tiefer und tiefer begraben, anstatt sie zu lösen, wobei nicht erwähnt wird, dass ein unsachgemäßer Gebrauch einen weiteren Haufen Boilerplate-Code erzeugt, der zukünftige Wartung erfordert.

Wenn etwas, das von einer Methode zurückgegeben wird, null sein kann und der aufrufende Code eine Entscheidung darüber treffen muss, sollte ein früherer Aufruf erfolgen, der den Status sicherstellt. 

Denken Sie auch daran, dass das Null-Objekt-Muster bei Nichtbeachtung speicherhungrig ist. Zu diesem Zweck sollte die Instanz eines NullObjects von den Eigentümern gemeinsam genutzt werden und darf nicht für jeden dieser Objekte eine einzige Instanz sein.

Ich würde auch nicht empfehlen, dieses Muster zu verwenden, wenn der Typ eine primitive Typendarstellung sein soll - wie mathematische Entitäten, die keine Skalare sind: Vektoren, Matrizen, komplexe Zahlen und POD-Objekte (Plain Old Data), die den Zustand enthalten sollen in Form von integrierten Java-Typen. Im letzteren Fall würden Sie Getter-Methoden mit beliebigen Ergebnissen aufrufen. Was soll beispielsweise eine NullPerson.getName () -Methode zurückgeben? 

Solche Fälle sollten in Betracht gezogen werden, um absurde Ergebnisse zu vermeiden.

14
spectre

Darf ich es allgemeiner beantworten!

Wir normalerweise stehen vor diesem Problem, wenn die Methoden die Parameter in der Weise erhalten, wie wir sie nicht erwartet haben (schlechter Aufruf der Methode ist ein Fehler des Programmierers). Zum Beispiel: Sie erwarten ein Objekt, stattdessen eine Null. Sie erwarten einen String mit mindestens einem Zeichen, stattdessen erhalten Sie einen leeren String ...

Es gibt also keinen Unterschied zwischen:

if(object == null){
   //you called my method badly!

}

oder

if(str.length() == 0){
   //you called my method badly again!
}

Beide möchten sicherstellen, dass wir gültige Parameter erhalten haben, bevor wir andere Funktionen ausführen.

Wie in einigen anderen Antworten erwähnt, können Sie das Muster Design by contract verwenden, um die oben genannten Probleme zu vermeiden. Siehe http://en.wikipedia.org/wiki/Design_by_contract

Um dieses Muster in Java zu implementieren, können Sie grundlegende Java-Annotationen wie javax.annotation.NotNull oder komplexere Bibliotheken wie Hibernate Validator verwenden.

Nur eine Probe:

getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)

Jetzt können Sie die Kernfunktion Ihrer Methode sicher entwickeln, ohne Eingabeparameter überprüfen zu müssen. Sie schützen Ihre Methoden vor unerwarteten Parametern.

Sie können einen Schritt weiter gehen und sicherstellen, dass in Ihrer Anwendung nur gültige Pojos erstellt werden können. (Beispiel von der Website für den Ruhezustand des Validators)

public class Car {

   @NotNull
   private String manufacturer;

   @NotNull
   @Size(min = 2, max = 14)
   private String licensePlate;

   @Min(2)
   private int seatCount;

   // ...
}
14
Alireza Fattahi
  1. Initialisieren Sie niemals Variablen auf Null.
  2. Wenn (1) nicht möglich ist, initialisieren Sie alle Sammlungen und Arrays mit leeren Sammlungen/Arrays.

Wenn Sie dies in Ihrem eigenen Code tun, können Sie! = Nullprüfungen vermeiden.

In den meisten Fällen scheinen Nullprüfungen Schleifen über Sammlungen oder Arrays zu schützen. Wenn Sie sie also leer initialisieren, benötigen Sie keine Nullprüfungen.

// Bad
ArrayList<String> lemmings;
String[] names;

void checkLemmings() {
    if (lemmings != null) for(lemming: lemmings) {
        // do something
    }
}



// Good
ArrayList<String> lemmings = new ArrayList<String>();
String[] names = {};

void checkLemmings() {
    for(lemming: lemmings) {
        // do something
    }
}

Es gibt einen winzigen Aufwand, aber es lohnt sich für saubereren Code und weniger NullPointerExceptions.

13
Stuart Axon

Dies ist der häufigste Fehler, der bei den meisten Entwicklern aufgetreten ist.

Wir haben viele Möglichkeiten, damit umzugehen.

Ansatz 1:

org.Apache.commons.lang.Validate //using Apache framework

notNull (Objektobjekt, String-Nachricht) 

Ansatz 2:

if(someObject!=null){ // simply checking against null
}

Ansatz 3:

@isNull @Nullable  // using annotation based validation

Ansatz 4:

// by writing static method and calling it across whereever we needed to check the validation

static <T> T isNull(someObject e){  
   if(e == null){
      throw new NullPointerException();
   }
   return e;
}
13
public static <T> T ifNull(T toCheck, T ifNull) {
    if (toCheck == null) {
           return ifNull;
    }
    return toCheck;
}
10
tltester

Java 8 hat eine neue Klasse Optional in Java.util-Paket eingeführt.

Vorteile von Java 8 Optional:

1.) Nullprüfungen sind nicht erforderlich.
2.) Keine NullPointerException zur Laufzeit mehr.
3.) Wir können saubere und ordentliche APIs entwickeln. 

Optional - Ein Containerobjekt, das einen Wert ungleich Null enthalten kann oder nicht. Wenn ein Wert vorhanden ist, gibt isPresent () true zurück und get () gibt den Wert zurück.

Weitere Informationen finden Sie hier: Oracle-Dokumente: - https://docs.Oracle.com/javase/8/docs/api/Java/util/Optional.html

9
NeeruSingh

Sie können FindBugs verwenden. Sie haben auch ein Eclipse plugin), mit dem Sie unter anderem doppelte Nullprüfungen finden können. Beachten Sie jedoch, dass Sie sich manchmal für eine defensive Programmierung entscheiden sollten. Es gibt auch Verträge für Java , die hilfreich sein können.

8
Leen Toelen

Ich befolge die folgenden Richtlinien, um Nullprüfungen zu vermeiden.

  1. Vermeiden Siefaule Initialisierungvon Membervariablen so weit wie möglich. Initialisieren Sie die Variablen in der Deklaration selbst. Dadurch werden NullPointerExceptions behandelt. 

  2. Entscheiden Sie sich früh im Zyklus fürmutabilityvon Membervariablen. Verwenden Sie Sprachkonstrukte wie final Schlüsselwort effektiv. 

  3. Wenn Sie wissen, dass Erweiterungen für die Methode nicht geändert werden, deklarieren Sie sie als final.

  4. Begrenzen Sie die-Mutationvon Daten so weit wie möglich. Einige Variablen können in einem Konstruktor erstellt werden und können niemals geändert werden.Entferne öffentliche Setter-Methoden, sofern sie nicht wirklich erforderlich sind.

    Z.B. Angenommen, eine Klasse in Ihrer Anwendung (A.Java) verwaltet eine Auflistung wie HashMap. Geben Sie keine public Getter-Methode in A.Java an und erlauben Sie B.Java, ein Element direkt in Map hinzuzufügen. Geben Sie stattdessen eine API in A.Java an, die ein Element zur Auflistung hinzufügt. 

    // Avoid
    a.getMap().put(key,value)
    
    //recommended
    
    public void addElement(Object key, Object value){
           // Have null checks for both key and value here : single place
           map.put(key,value);
    }
    
  5. Und schließlich verwenden Sie try{} catch{} finally{}-Blöcke effektiv an den richtigen Stellen.

7
Ravindra babu

Seit Java 7 existiert die Klasse Java.util.Objects.

Seit Java 8 können Sie jedoch die Objects.isNull(var)- und Objects.nonNull(var)-Methoden der Objects-Klasse für die Überprüfung des Nullzeigers verwenden.

Zum Beispiel,

String var1 = null;
Date var2 = null;
Long var3 = null;

if(Objects.isNull(var1) && Objects.isNull(var2) && Objects.isNull(var3))
    System.out.println("All Null");
else if (Objects.nonNull(var1) && Objects.nonNull(var2) && Objects.nonNull(var3))
    System.out.println("All Not Null");
7
Philip John

Alles in allem, um Aussagen zu vermeiden

if (object != null) {
    ....
}
  1. seit Java 7 können Sie Objects-Methoden verwenden:

    Objects.isNull (Objekt)

    Objects.nonNull (Objekt)

    Objects.requireNonNull (Objekt)

    Objects.equals (object1, object2)

  2. seit Java 8 können Sie die optionale Klasse verwenden ( Wann verwenden Sie

object.ifPresent(obj -> ...); Java 8

object.ifPresentOrElse(obj -> ..., () -> ...); Java 9

  1. verlassen Sie sich auf den Methodenvertrag ( JSR 305 ) und verwenden Sie Find Bugs . Kennzeichnen Sie Ihren Code mit den Anmerkungen @javax.annotation.Nullable und @javax.annotation.Nonnnul. Auch Voraussetzungen sind vorhanden.

    Vorbedingung.checkNotNull (Objekt);

  2. In besonderen Fällen (z. B. für Zeichenfolgen und Sammlungen) können Sie Dienstprogrammmethoden von Apache-Commons (oder Google Guava) verwenden:

public static boolean isEmpty (CharSequence cs) // Apache CollectionUtils

public static boolean isEmpty (Collection coll) // Apache StringUtils

public static boolean isEmpty (Map Map) // Apache MapUtils

public static boolean isNullOrEmpty (@Nullable String string) // Guava-Zeichenfolgen

  1. Wenn Sie bei null einen Standardwert zuweisen müssen, verwenden Sie Apache commons lang

public static Object defaultIfNull (Objektobjekt, Object defaultValue)

6
fbokovikov

Eine weitere Alternative:

Die folgende einfache Funktion hilft beim Ausblenden der Nullprüfung (ich weiß nicht warum, aber ich habe sie nicht in derselben common library gefunden):

public static <T> boolean isNull(T argument) {
    return (argument == null);
}

Du könntest jetzt schreiben

if (!isNull(someobject)) {
    someobject.doCalc();
}

das ist IMO eine bessere Möglichkeit, != null auszudrücken.

6
jeha

Wo immer Sie ein Array oder einen Vektor übergeben, initialisieren Sie diese mit leeren anstelle von null. - Auf diese Weise können Sie viele Überprüfungen auf null vermeiden und alles ist gut :)

public class NonNullThing {

   Vector vectorField = new Vector();

   int[] arrayField = new int[0];

   public NonNullThing() {

      // etc

   }

}
5
Stuart Axon

Sie können die meisten vermeiden, um NullPointerException zu vermeiden, indem Sie einfach den meisten anderen Antworten auf die Frage folgen. Ich möchte nur ein paar weitere Möglichkeiten hinzufügen, die in _Java 9_ , um mit diesem Szenario angemessen umzugehen und auch einige der älteren zu präsentieren, kann ebenfalls verwendet werden, was Ihren Aufwand verringert.

  1. public static boolean isNull(Object obj)

    Gibt true zurück, wenn die angegebene Referenz null ist, andernfalls false.

    Seit Java 1.8

  2. public static boolean nonNull(Object obj)

    Gibt true zurück, wenn die angegebene Referenz nicht null ist, andernfalls false.

    Seit Java 1.8

  3. public static <T> T requireNonNullElse​(T obj, T defaultObj)

    Gibt das erste Argument zurück, wenn es nicht null ist, und gibt ansonsten das zweite Argument zurück, das nicht null ist.

    Seit Java 9

  4. public static <T> T requireNonNullElseGet​(T obj, Supplier<? extends T> supplier)

    Gibt das erste Argument zurück, wenn es nicht null ist, und gibt ansonsten den Wert von supplier.get () zurück, der nicht null ist.

    Seit Java 9

  5. public static <T> T requireNonNull​(T obj, Supplier<String> messageSupplier)

    Überprüft, ob die angegebene Objektreferenz nicht null ist, und löst andernfalls eine angepasste NullPointerException aus.

    Seit Java 1.8

Weitere Details zu den oben genannten Funktionen finden Sie hier .

5
Mukesh A

Ich finde, dass Guava-Voraussetzungen in diesem Fall sehr nützlich sind. Ich mag es nicht, Nullen auf Nullzeigerausnahmen zu belassen, da eine NPE nur durch das Auffinden der Zeilennummer verstanden werden kann. Die Zeilennummern in der Fertigungsversion und in der Entwicklungsversion können unterschiedlich sein.

Mit Guava-Vorbedingungen kann ich Nullparameter überprüfen und eine aussagekräftige Ausnahmemeldung in einer Zeile definieren.

Zum Beispiel,

Preconditions.checkNotNull(paramVal, "Method foo received null paramVal");
5
Gal Morad

Sie können vor dem Methodenaufruf einen Interceptor verwenden. Das ist, was Aspektorientierte Programmierung Fokus.

Angenommen, M1 (Object test) ist eine Methode und M2 ist eine Methode, bei der ein Aspekt vor dem Methodenaufruf M2(Object test2) angewendet wird. Wenn test2 != null, dann rufen Sie M1 an, sonst machen Sie eine andere Sache. Es funktioniert für alle Methoden, für die Sie einen Aspekt anwenden möchten. Wenn Sie einen Aspekt für ein Instanzfeld und einen Konstruktor anwenden möchten, können Sie AspectJ verwenden. Frühling kann auch die beste Wahl für einen Methodenaspekt sein.

4

In Java 8 können Sie den Typ T für local-variable/field/method_argument/method-return-type verwenden, wenn ihm nie null zugewiesen wurde (und nicht nach null suchen) oder Typ Optional<T>, wenn es null sein kann. Verwenden Sie dann die Methode map für die Verarbeitung von T -> und die Methode flatMap für die Verarbeitung von T -> Optional<R>:

class SomeService {
    @Inject
    private CompanyDao companyDao;

    // return Optional<String>
    public Optional<String> selectCeoCityByCompanyId0(int companyId) {
        return companyDao.selectById(companyId)
                .map(Company::getCeo)
                .flatMap(Person::getHomeAddress)
                .flatMap(Address::getCity);
    }

    // return String + default value
    public String selectCeoCityByCompanyId1(int companyId) {
        return companyDao.selectById(companyId)
                .map(Company::getCeo)
                .flatMap(Person::getHomeAddress)
                .flatMap(Address::getCity)
                .orElse("UNKNOWN");
    }

    // return String + exception
    public String selectCeoCityByCompanyId2(int companyId) throws NoSuchElementException {
        return companyDao.selectById(companyId)
                .map(Company::getCeo)
                .flatMap(Person::getHomeAddress)
                .flatMap(Address::getCity)
                .orElseThrow(NoSuchElementException::new);
    }
}

interface CompanyDao {
    // real situation: no company for such id -> use Optional<Company> 
    Optional<Company> selectById(int id);
}

class Company {
    // company always has ceo -> use Person 
    Person ceo;
    public Person getCeo() {return ceo;}
}

class Person {
    // person always has name -> use String
    String firstName;
    // person can be without address -> use Optional<Address>
    Optional<Address> homeAddress = Optional.empty();

    public String getFirstName() {return firstName;}   
    public Optional<Address> getHomeAddress() {return homeAddress;}
}

class Address {
    //  address always contains country -> use String
    String country;
    //  city field is optional -> use Optional<String>
    Optional<String> city = Optional.empty();

    String getCountry() {return country;}    
    Optional<String> getCity() {return city;}
}
4
Ivan Golovach

Wenn Sie Java8 oder höher verwenden, wählen Sie isNull(yourObject) von Java.util.Objects aus.

Beispiel:-

String myObject = null;

Objects.isNull(myObject); //will return true
3
Jobin Joseph

Java 8 hat jetzt eine optionale Klasse, die das Objekt in Betracht zieht, und wenn ein Wert vorhanden ist, gibt isPresent () den Wert true zurück, und get () gibt den Wert zurück.

http://www.Oracle.com/technetwork/articles/Java/java8-optional-2175753.html

3
sidgate

Sie können das Checker-Framework (mit JDK 7 und höher) auch verwenden, um statisch auf Nullwerte zu prüfen. Dies kann viele Probleme lösen, erfordert jedoch die Ausführung eines zusätzlichen Tools, das derzeit nur mit OpenJDK AFAIK funktioniert. https://checkerframework.org/

3
Jochen

Java 8 hat eine neue Klasse Optional im Java.util-Paket eingeführt. Es wird verwendet, um darzustellen, dass ein Wert vorhanden oder nicht vorhanden ist. Der Hauptvorteil dieses neuen Konstrukts besteht darin, dass nicht mehr zu viele Nullprüfungen und NullPointerException durchgeführt werden. Es vermeidet jegliche Laufzeit-NullPointerExceptions und unterstützt uns bei der Entwicklung sauberer und ordentlicher Java APIs oder Anwendungen. Wie Sammlungen und Arrays ist es auch ein Container, der höchstens einen Wert enthält.

Nachfolgend finden Sie einige nützliche Links, denen Sie folgen können

https://www.mkyong.com/Java8/Java-8-optional-in-depth/

https://dzone.com/articles/Java-8-optional-avoid-null-and

3
rohit prakash

OK, ich habe das jetzt millionenfach technisch beantwortet, aber ich muss das sagen, weil dies eine unendliche Diskussion mit Java-Programmierern ist.

Tut mir leid, aber ich stimme nicht zu. Der Grund, warum wir in Java auf Null testen müssen, ist, dass Java-Programmierer nicht wissen, wie sie mit Speicher umgehen. 

Ich sage das, weil ich lange Erfahrung mit der Programmierung in C++ habe und wir dies nicht tun. Mit anderen Worten, Sie müssen nicht Beachten Sie, dass in Java, wenn Sie einen baumelnden Zeiger treffen, eine normale Ausnahme auftritt. In C++ wird diese Ausnahme normalerweise nicht abgefangen und das Programm beendet.

Will das nicht tun Folgen Sie dann einigen einfachen Regeln wie C/C++.

Instanziieren Sie die Dinge nicht so leicht, denke, dass jedes "Neue" Sie in eine Menge Ärger bringen kann, und folgen Sie diesen einfachen Regeln.

Eine Klasse darf nur auf drei Arten auf den Speicher zugreifen ->

  1. Es kann Klassenmitglieder "HABEN", und sie werden diesen Regeln folgen:

    1. ALLE "HAS" -Member werden im Konstruktor "neu" erstellt.
    2. Sie werden in destructor oder einer entsprechenden close () -Funktion in Java für diese Klasse schließen und die Zuordnung aufheben.

Dies bedeutet, dass Sie (genau wie Java) im Auge behalten müssen, wer Eigentümer oder übergeordnetes Element jeder Ressource ist und diesen Besitz respektieren. Ein Objekt wird nur von der Klasse gelöscht, die es erstellt hat. Auch ->

  1. Einige Mitglieder werden "USED" sein, aber keine eigenen oder "HAVE". Dies sind "OWN" in einer anderen Klasse und werden als Argumente an den Konstruktor übergeben. Da diese einer anderen Klasse gehören, werden wir NIEMALS löschen oder schließen. Dies kann nur die übergeordnete Klasse.

  2. Eine Methode in einer Klasse kann auch lokale Objekte für die interne Verwendung instanziieren, die NIEMALS über die Klasse hinausgehen, oder sie sollten normale "has" -Objekte gewesen sein.

Damit dies alles funktioniert, benötigen Sie ein diszipliniertes Design mit Klassen in Hierarchieform und ohne Zyklen.

Bei diesem Design UND nach den obigen Regeln gibt es keine Möglichkeit, dass eine untergeordnete Klasse in einem Hierarchiedesign jemals auf einen Zeiger zugreifen kann, der zerstört wurde, da dies bedeutet, dass ein übergeordnetes Element vor einem untergeordneten Element zerstört wurde erlaube es.

Denken Sie außerdem daran, dass Sie beim Start Ihres Systems von oben nach unten in der Hierarchie bauen und von unten nach oben zerstören sollten. Sie werden niemals irgendwo einen Nullzeiger haben oder jemand verstößt gegen die Regeln.

2
Alex Vaz

Der Weg, unnötigen null-checks zu vermeiden, ist einfach zu sagen:

You need to know which variables can be null, and which cannot, and you need to be confident about which category a given variable fall into.

Obwohl es einfach gesagt werden kann, ist es schwieriger, es zu erreichen. Der Schlüssel liegt im confident-Teil, denn wie können Sie sicher sein, dass eine Variable nicht null sein kann?

Es gibt keine schnellen, einfachen Antworten darauf, aber hier sind einige Hinweise:

  1. Code reinigen. Das Wichtigste, um über das Verhalten eines Codeabschnitts nachdenken zu können, ist, dass es in einer leicht verständlichen Angelegenheit geschrieben wird. Benennen Sie Ihre Variablen basierend auf dem, was sie repräsentieren, benennen Sie Ihre Methoden nach dem, was sie tun, und wenden Sie den Single responsibility principle (die S in SOLID: http://en.wikipedia.org/wiki/SOLID_(object-oriented_design) an bedeutet, dass jeder Code eine einzige Verantwortung haben sollte und dies und nichts anderes tun sollte). Sobald Ihr Code sauber ist, ist es viel einfacher, darüber nachzudenken, auch über mehrere Codeschichten/-ebenen hinweg. Wenn Sie mit chaotischem Code verstehen, was eine Methode tut, vergessen Sie vielleicht, warum Sie die Methode überhaupt lesen. (Tipp: Lesen Sie "Clean Code" von Robert C. Martin)

  2. Vermeiden Sie, null-Werte zurückzugeben. Wenn ein null-Wert dazu führt, dass Ihr Programm nicht ordnungsgemäß funktioniert, werfen Sie stattdessen eine exception aus (fügen Sie die entsprechende Fehlerbehandlung hinzu.) Fälle, in denen die Rückgabe eines null-Werts zulässig ist, ist beispielsweise der Versuch, ein Objekt aus der Datenbank abzurufen. Schreiben Sie in diesen Fällen Code, der die null-Werte verarbeitet, und notieren Sie hinter Ihrem Ohr, dass hier etwas vorhanden ist, das null zurückgeben könnte. Behandelte zurückgegebene null-Werte so nahe an den Aufrufer der Methode, dass null zurückgegeben wird (geben Sie sie nicht einfach blind zurück in die Aufrufkette.)

  3. Übergeben Sie NIEMALS explizite null-Werte als Parameter (zumindest nicht zwischen Klassen). Wenn Sie sich jemals in einer Position befinden, in der die Übergabe eines null- Parameters die einzige Option ist, ist das Erstellen einer neuen Methode ohne diesen Parameter der richtige Weg. 

  4. Bestätigen Sie Ihre Eingabe! Identifizieren Sie die "Einstiegspunkte" für Ihre Anwendung. Sie können alles von Webservices, REST-Diensten, Remote-EJB-Klassen, Controllern usw. abfragen. Für jede Methode in diesen Einstiegspunkten fragen Sie sich: "Wird diese Methode korrekt ausgeführt, wenn dieser Parameter null ist?" Wenn die Antwort nein lautet, fügen Sie Validate.notNull(someParam, "Can't function when someParam is null!"); hinzu. Wenn der erforderliche Parameter fehlt, wird eine IllegalArgumentException ausgegeben. Das Gute an dieser Art der Validierung in den Einstiegspunkten ist, dass Sie in dem auszuführenden Code vom Einstiegspunkt aus leicht davon ausgehen können, dass diese Variable niemals null sein wird! Wenn dies fehlschlägt, wird das Debuggen am Einstiegspunkt viel einfacher, als wenn Sie nur eine NullPointerException tief in Ihrem Code haben würden, da ein solcher Ausfall nur eine Sache bedeuten kann: Der Client hat dies nicht getan Senden Sie Ihnen alle erforderlichen Informationen. In den meisten Fällen möchten Sie alle Eingabeparameter überprüfen. Wenn Sie sich in einer Position befinden, in der Sie viele null- Werte zulassen müssen, kann dies ein Zeichen für eine schlecht entworfene Schnittstelle sein, die zur Anpassung an die Anforderungen überarbeitet oder ergänzt werden muss der Kunden.

  5. Wenn Sie mit Collections arbeiten, geben Sie einen leeren Wert anstelle von null zurück! 

  6. Verwenden Sie beim Arbeiten mit einer Datenbank not null- Einschränkungen. Auf diese Weise wissen Sie, dass ein aus der Datenbank gelesenen Wert nicht null sein kann, und Sie müssen nicht danach prüfen.

  7. Strukturieren Sie Ihren Code und bleiben Sie dabei. Auf diese Weise können Sie Annahmen über das Verhalten des Codes treffen. Wenn beispielsweise alle Eingaben für Ihre Anwendung überprüft werden, können Sie davon ausgehen, dass diese Werte niemals null sind. 

  8. Wenn Sie dies nicht bereits tun, schreiben Sie automatisierte Tests Ihres Codes. Durch das Schreiben von Tests werden Sie über Ihren Code nachdenken und werden auch sicherer, dass er das tut, was er soll. Durch automatisierte Tests werden Sie auch während des Refactorings vor Fehlern geschützt, indem Sie sofort wissen, dass dieser Code nicht das tut, was er zuvor getan hat.

Sie müssen natürlich noch eine Nullprüfung durchführen, aber sie kann auf das Nötigste reduziert werden (dh in der Situation, in der know möglicherweise einen Nullwert erhält, und nicht überall, nur um sicher zu gehen.) Wenn es darum geht Um Null-Überprüfungen durchzuführen, ziehe ich eigentlich den ternären Operator vor (aber mit Vorsicht, wenn Sie mit dem Schachteln beginnen, werden sie wirklich unordentlich.)

public String nullSafeToString(final Object o) {
    return o != null ? o.toString() : "null";
}
2
Tobb

Zunächst können wir nicht alle Nullbedingungen wirklich entfernen. Wir können sie mit den @NotNull- und @Nullable-Annotationen reduzieren (wie bereits erwähnt). Dies muss jedoch durch einige Rahmenbedingungen unterstützt werden. Hier kann OVal helfen.

Die Grundidee ist, dass object/parameters/constructor immer Vorbedingungen erfüllen muss. Sie können eine ganze Reihe von Voraussetzungen haben, z. B. Nullable, NotNull und OVal sorgen dafür, dass sich ein Objekt beim Aufruf in einem konsistenten Zustand befindet.

Ich denke, OVal verwendet intern AspectJ, um die Vorbedingungen zu überprüfen.

@Guarded
public class BusinessObject
{
  public BusinessObject(@NotNull String name)
  {
    this.name = name;
  }

  ...
}

Zum Beispiel,

// Throws a ConstraintsViolatedException because parameter name is null
BusinessObject bo = new BusinessObject(null);
2
Vinay Lodha

Wir haben Apache-Bibliotheken (Apache Commons) für dieses Problem verwendet.

ObjectUtils.equals(object, null)

oder

CollectionUtils.isEmpty(myCollection);

oder 

StringUtils.isEmpty("string");

Ich mag die vorige Antwort, in der Praxis, anfängliche Standardwerte oder leere Mengen für Sammlungen anzugeben, um den Bedarf zu minimieren.

Dies können einfache Verwendungen sein, die Sie davon abhalten, eine NullPointerException zu verwenden oder eine leere Auflistung zu verwenden. Dies beantwortet nicht die Frage, was mit dem Nullobjekt zu tun ist, aber diese bieten einige Überprüfungen für grundlegende Überprüfungen des Objekts oder der Objektgruppe. 

Hoffe das hilft. 

1
iowatiger08

Ich bevorzuge das

public void simpleFunc(SomeObject someObject){
    someObject = someObject != null ? someObject : new SomeObject(null);
    someObject.doSomething();
}

In meinem Beispiel behandelt SomeObject natürlich einen Null-Parameter. Zum Beispiel, ein solches Ereignis zu protokollieren und nichts mehr zu tun.

1
drzymala

Mit Java 8 können Sie einen Lieferanten an eine Hilfsmethode wie unten übergeben übergeben.

if(CommonUtil.resolve(()-> a.b().c()).isPresent()) {

}

Oben ersetzt Kesselkennzeichencode wie unten.

if(a!=null && a.b()!=null && a.b().c()!=null) {

}

//CommonUtil.Java

 public static <T> Optional<T> resolve(Supplier<T> resolver) {
        try {
            T result = resolver.get();
            return Optional.ofNullable(result);
        } catch (NullPointerException var2) {
            return Optional.empty();
        }
    }
1
nilesh

Mit Java 8-Lambdas können praktisch definierte Methoden definiert werden, die verschachtelte Nullprüfungen auf nahezu hübsche Weise behandeln.

void example() {
    Entry entry = new Entry();
    // This is the same as H-MANs solution 
    Person person = getNullsafe(entry, e -> e.getPerson());    
    // Get object in several steps
    String givenName = getNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.getGivenName());
    // Call void methods
    doNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.nameIt());        
}

/** Return result of call to f1 with o1 if it is non-null, otherwise return null. */
public static <R, T1> R getNullsafe(T1 o1, Function<T1, R> f1) {
    if (o1 != null) return f1.apply(o1);
    return null; 
}

public static <R, T0, T1> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, R> f2) {
    return getNullsafe(getNullsafe(o0, f1), f2);
}

public static <R, T0, T1, T2> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Function<T2, R> f3) {
    return getNullsafe(getNullsafe(o0, f1, f2), f3);
}


/** Call consumer f1 with o1 if it is non-null, otherwise do nothing. */
public static <T1> void doNullsafe(T1 o1, Consumer<T1> f1) {
    if (o1 != null) f1.accept(o1);
}

public static <T0, T1> void doNullsafe(T0 o0, Function<T0, T1> f1, Consumer<T1> f2) {
    doNullsafe(getNullsafe(o0, f1), f2);
}

public static <T0, T1, T2> void doNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Consumer<T2> f3) {
    doNullsafe(getNullsafe(o0, f1, f2), f3);
}


class Entry {
    Person getPerson() { return null; }
}

class Person {
    Name getName() { return null; }
}

class Name {
    void nameIt() {}
    String getGivenName() { return null; }
}

(Diese Antwort wurde zuerst hier veröffentlicht.)

1
Lii

Kotlin mit Nullsicherheit ist eine elegante Alternative, bedeutet aber eine größere Änderung.

0
Francis

Bei Dienstprogrammklassen können Sie überprüfen, dass die Parameter nicht null sind.

In allen anderen Fällen müssen Sie möglicherweise nicht. Verwenden Sie die Kapselung so weit wie möglich und reduzieren Sie so die Stellen, an denen Sie versucht sind, nach Null zu suchen.

0
daniel

Sie können Ihre Klasse mit Unit Testing mithilfe eines Frameworks wie JUnit ..__ koppeln. Auf diese Weise wird Ihr Code sauber (keine unnötigen Überprüfungen) und Sie werden sicher sein, dass Ihre Instanzen nicht null sind.

Dies ist (von vielen Gründen) ein guter Grund, Unit Testing zu verwenden.

0
Mehdi

Ein Nullobjektmuster kann als Lösung für dieses Problem verwendet werden. Dazu muss die Klasse von someObject geändert werden. 

public abstract class SomeObject {
   public abstract boolean isNil();
}

public class NullObject extends SomeObject {
   @Override
   public boolean isNil() {
      return true;
   }
}
public class RealObject extends SomeObject {
   @Override
   public boolean isNil() {
      return false;
   }
}

Jetzt ist es zu überprüfen,

 if (someobject != null) {
    someobject.doCalc();
}

Wir können benutzen,

if (!someObject.isNil()) {
   someobject.doCalc();
}

Referenz: https://www.tutorialspoint.com/design_pattern/null_object_pattern.htm

0
Vidura Mudalige

Eine Option haben Sie

  • Verwenden Sie checker framework @s @RequiresNonNull für Methoden. Zum Beispiel erhalten Sie dies, wenn Sie eine als solche kommentierte Methode mit einem NULL-Argument aufrufen. Es wird während des Kompilierens fehlschlagen, noch bevor der Code ausgeführt wird! da es zur Laufzeit NullPointerException ist

    @RequiresNonNull(value = { "#1" })
    static void check( Boolean x) {
        if (x) System.out.println("true");
        else System.out.println("false");
    }
    
    public static void main(String[] args) {
    
    
        check(null);
    
    }
    

bekommt 

[ERROR] found   : null
[ERROR] required: @Initialized @NonNull Boolean
[ERROR] -> [Help 1]

Es gibt andere Methoden wie Java 8 verwenden, Guava-Anmerkungen, Null-Objekt-Muster usw.

0
Binod Pant

Eine andere Alternative zum! = Null-Check ist (wenn Sie ihn nicht designmäßig loswerden können):

Optional.ofNullable(someobject).ifPresent(someobject -> someobject.doCalc());

oder

Optional.ofNullable(someobject).ifPresent(SomeClass::doCalc);

Mit SomeClass als Typ eines Objekts.

Sie können jedoch keinen Rückgabewert von doCalc () erhalten, was nur für void-Methoden nützlich ist.

0

Ein funktionaler Ansatz kann dabei helfen, die wiederkehrenden Nullprüfungen zu umgehen und anonymen Code wie in dem folgenden Beispiel auszuführen.

    BiConsumer<Object, Consumer<Object>> consumeIfPresent  = (s,f) ->{
        if(s!=null) {
            f.accept(s);
        }
    };

    consumeIfPresent.accept(null, (s)-> System.out.println(s) );
    consumeIfPresent.accept("test", (s)-> System.out.println(s));

    BiFunction<Object, Function<Object,Object>,Object> executeIfPresent  = (a,b) ->{
        if(a!=null) {
            return b.apply(a);
        }
        return null;
    };
    executeIfPresent.apply(null, (s)-> {System.out.println(s);return s;} );
    executeIfPresent.apply("test", (s)-> {System.out.println(s);return s;} );
0
Ramprabhu