Null-Check in einer erweiterten for-Schleife

172

Was ist der beste Weg, um in einer for-Schleife in Java gegen Null zu schützen?

Das scheint hässlich:

if (someList != null) {
    for (Object object : someList) {
        // do whatever
    }
}

Oder

if (someList == null) {
    return; // Or throw ex
}
for (Object object : someList) {
    // do whatever
}

Es könnte keinen anderen Weg geben. Sollten sie es in das forKonstrukt selbst eingefügt haben , wenn es null ist, dann führen Sie die Schleife nicht aus?

fastcodejava
quelle
2
Sie sind wahrscheinlich besser dran, eine NPE zu werfen. nullist nicht dasselbe wie eine leere Sammlung.
Tom Hawtin - Tackline
6
@ GregMattes Wie ist die Februar-Frage ein Duplikat der Oktober-Frage?
Val
1
Sie müssen nur Collections.nonNullElementsIn (...) verwenden: stackoverflow.com/a/34913556/5637185
Jeffrey Dilley

Antworten:

227

Sie sollten besser überprüfen, woher Sie diese Liste beziehen.

Eine leere Liste ist alles, was Sie brauchen, da eine leere Liste nicht fehlschlägt.

Wenn Sie diese Liste von einem anderen Ort erhalten und nicht wissen, ob sie in Ordnung ist oder nicht, können Sie eine Dienstprogrammmethode erstellen und wie folgt verwenden:

for( Object o : safe( list ) ) {
   // do whatever 
 }

Und natürlich safewäre:

public static List safe( List other ) {
    return other == null ? Collections.EMPTY_LIST : other;
}
OscarRyz
quelle
57
Beachten Sie, dass Collections.emptyList () das Zuweisen eines zusätzlichen Objekts (IIRC) vermeidet.
Jon Skeet
7
@ Jon: Ich habe mich immer gefragt, wozu emptyList java.sun.com/j2se/1.5.0/docs/api/java/util/… gut ist. Was ist IIRC?
OscarRyz
11
IIRC = "Wenn ich mich richtig erinnere". Und ja, es gibt eine Singleton-Instanz, die für alle Aufrufe von Collections.emptyList () zurückgegeben wird.
ColinD
Dies ... beantwortet die Frage nicht wirklich. Warum wird die Antwort akzeptiert?
Christopher Wirt
1
@ChristopherWirt, weil es die Frage beantwortet: D
Tarik
100

Sie könnten möglicherweise eine Hilfsmethode schreiben, die eine leere Sequenz zurückgibt, wenn Sie null übergeben:

public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
    return iterable == null ? Collections.<T>emptyList() : iterable;
}

Dann benutze:

for (Object object : emptyIfNull(someList)) {
}

Ich glaube nicht, dass ich das tatsächlich tun würde - normalerweise würde ich Ihre zweite Form verwenden. Insbesondere das "oder throw ex" ist wichtig - wenn es wirklich nicht null sein sollte, sollten Sie definitiv eine Ausnahme auslösen. Sie wissen, dass etwas schief gelaufen ist, aber Sie kennen das Ausmaß des Schadens nicht. Früh abbrechen.

Jon Skeet
quelle
3
Ich würde den Listenparameter Iterable <T> in iterable Iterable <T> ändern, da nicht jede iterable eine Liste ist.
Lombo
Seien Sie vorsichtig mit dieser Methode: Aufgrund der Verwendung der Collections-Klasse ist Ihre Liste bei der Verwendung dieser Methode unveränderlich
Tanorix
@ Tanorix: Auf welche Weise?
Jon Skeet
@JonSkeet Sie können sehen, dass die Klasse emptyList () der Sammlungen eine unveränderliche Liste zurückgibt: docs.oracle.com/javase/8/docs/api/java/util/…. Wenn der Benutzer also nicht möchte, dass seine Liste unveränderlich ist, kann dies möglich sein problematisch sein
Tanorix
@tanorix: Aber der Sinn dieser Frage geht es um Iterieren den zurückgegebenen Wert über. Das ändert nichts daran. Das ist der Grund, warum der Rückgabetyp emptyIfNulllautet Iterable<T>- es gibt die unglückliche removeMethode Iterator<T>, aber das ist der einzige veränderbare Aspekt davon (und wenn Sie eine leere Sammlung haben, warum versuchen Sie, etwas daraus zu entfernen?) Es ist nicht klar, was Sie tun. Ich widerspreche hier.
Jon Skeet
29

Es ist bereits 2017 und Sie können jetzt Apache Commons Collections4 verwenden

Die Verwendung:

for(Object obj : ListUtils.emptyIfNull(list1)){
    // Do your stuff
}

Sie können dieselbe null-sichere Prüfung auch für andere Collection-Klassen mit durchführen CollectionUtils.emptyIfNull.

Fred Pym
quelle
2
Funktioniert jedoch erstellt unnötiges Listenobjekt. Ein CollectionUtils.ifNotEmpty ist möglicherweise ausführlicher, aber effizienter und schneller. Nicht, dass es viel
Lawrence
2
2017 würde ich List.emptyIfNull (list1)
Dima
3
@Lawrence, die Methode erstellt keine neuen Listenobjekte, sondern verwendet sie Collections.emptyList()intern, was wiederum immer dieselbe vorab zugewiesene leere, nicht änderbare Liste zurückgibt.
Yoory N.
Was ist, wenn Sie myobject.getCompanies (). GetAddresses () aufrufen und beide eine Liste zurückgeben und beide null sein können?
Pulver366
9

Mit Java 8 Optional:

for (Object object : Optional.ofNullable(someList).orElse(Collections.emptyList())) {
    // do whatever
}
holmis83
quelle
1
Es ist ausführlicher als ein einfacher ternärer Operator someList != null ? someList : Collections.emptyList()und erstellt und wirft sofort eine OptionalObjektinstanz weg .
Yoory N.
2
Wie sind diese Monsterlinien eleganter als eine einfache if (someList == null) -Anweisung? Lassen Sie uns einen Bankantrag in einer Zeile schreiben ...
Andreas Panagiotidis
8

Verwendung ArrayUtils.nullToEmptyaus der commons-langBibliothek für Arrays

for( Object o : ArrayUtils.nullToEmpty(list) ) {
   // do whatever 
}

Diese Funktionalität ist in der commons-langBibliothek vorhanden, die in den meisten Java-Projekten enthalten ist.

// ArrayUtils.nullToEmpty source code 
public static Object[] nullToEmpty(final Object[] array) {
    if (isEmpty(array)) {
        return EMPTY_OBJECT_ARRAY;
    }
    return array;
}

// ArrayUtils.isEmpty source code
public static boolean isEmpty(final Object[] array) {
    return array == null || array.length == 0;
}

Dies ist die gleiche Antwort wie die Antwort von @OscarRyz, aber um des DRY- Mantras willen halte ich es für erwähnenswert. Siehe die Projektseite commons-lang . Hier ist die nullToEmptyAPI- Dokumentation und Quelle

Maven-Eintrag, der commons-langin Ihr Projekt aufgenommen werden soll, falls dies noch nicht geschehen ist.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>

Bietet commons-langdiese Funktionalität leider nicht für ListTypen. In diesem Fall müssten Sie eine Hilfsmethode wie zuvor erwähnt verwenden.

public static <E> List<E> nullToEmpty(List<E> list)
{
    if(list == null || list.isEmpty())
    {
        return Collections.emptyList();
    }
    return list;
}
sdc
quelle
7

Wenn Sie dies Listvon einem von Ihnen implementierten Methodenaufruf erhalten, geben Sie nicht zurück null, sondern geben Sie ein leeres zurück List.

Wenn Sie die Implementierung nicht ändern können, bleiben Sie bei der nullPrüfung. Wenn dies nicht der Fall sein sollte null, wird eine Ausnahme ausgelöst .

Ich würde mich nicht für die Hilfsmethode entscheiden, die eine leere Liste zurückgibt, da sie manchmal nützlich sein kann, aber dann würde man sich daran gewöhnen, sie in jeder Schleife aufzurufen, die man möglicherweise macht, um einige Fehler zu verbergen.

Lombo
quelle
4

Ich habe die obige Antwort geändert, sodass Sie nicht von Object aus wirken müssen

public static <T> List<T> safeClient( List<T> other ) {
            return other == null ? Collections.EMPTY_LIST : other;
}

und rufen Sie dann einfach die Liste auf

for (MyOwnObject ownObject : safeClient(someList)) {
    // do whatever
}

Erklärung: MyOwnObject: Wenn List<Integer>dann, ist MyOwnObject in diesem Fall Integer.

Haris Iltifat
quelle
1

Eine andere Möglichkeit, sich effektiv gegen eine Null in einer for-Schleife zu schützen, besteht darin, Ihre Sammlung mit Google Guava zu verpacken, Optional<T>da dies hoffentlich die Möglichkeit einer effektiv leeren Sammlung verdeutlicht, da vom Kunden erwartet wird, dass er prüft, ob die Sammlung vorhanden ist Optional.isPresent().

Nico de Wet
quelle
1

Für alle, die nicht daran interessiert sind, ihre eigene statische Null-Sicherheitsmethode zu schreiben, können Sie Folgendes verwenden: commons-lang's org.apache.commons.lang.ObjectUtils.defaultIfNull(Object, Object). Beispielsweise:

    for (final String item : 
    (List<String>)ObjectUtils.defaultIfNull(items, Collections.emptyList())) { ... }

ObjectUtils.defaultIfNull JavaDoc

Jacob Briscoe
quelle
Für mich ist diese Antwort die eleganteste
Truong Nguyen
0

Verwenden Sie eine Nullsichere CollectionUtils.isEmpty(Collection coll)Methode, um zu überprüfen, ob die angegebene Sammlung leer ist.

dafür import org.apache.commons.collections.CollectionUtils.

Maven-Abhängigkeit

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>
Swadeshi
quelle
-4
for (Object object : someList) {

   // do whatever
}  throws the null pointer exception.
user6315386
quelle