Проверка нуля в расширенном цикле for - PullRequest
159 голосов
/ 12 февраля 2010

Каков наилучший способ защиты от нуля в цикле for в Java?

Это кажется уродливым:

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

Или

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

Другого пути не может быть. Должны ли они поместить его в саму конструкцию for, если она равна нулю, тогда не запускать цикл?

Ответы [ 11 ]

214 голосов
/ 12 февраля 2010

Вам лучше проверить, откуда вы получили этот список.

Пустой список - это все, что вам нужно, потому что пустой список не выйдет из строя.

Если вы получили этот список откуда-то еще и не знаете, нормально ли это или нет, вы могли бысоздайте служебный метод и используйте его так:

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

И, конечно, safe будет:

public static List safe( List other ) {
    return other == null ? Collections.EMPTY_LIST : other;
}
94 голосов
/ 12 февраля 2010

Вы могли бы написать вспомогательный метод, который бы возвратил пустую последовательность, если вы передали значение null:

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

Тогда используйте:

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

Хотя я не думаю, что на самом деле сделал бы это, я бы обычно использовал вашу вторую форму. В частности, важно «или throw ex» - если оно действительно не должно быть нулевым, вы должны обязательно выбросить исключение. Вы знаете, что что-то пошло не так, но вы не знаете степень ущерба. Прервать рано.

25 голосов
/ 18 мая 2017

Уже 2017 год, и теперь вы можете использовать Apache Commons Collections4

Использование:

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

Вы можете сделать такую ​​же проверку на нулевую безопасность для других классов Collection с помощью CollectionUtils.emptyIfNull.

7 голосов
/ 17 августа 2017

с Java 8 Optional:

for (Object object : Optional.ofNullable(someList).orElse(Collections.emptyList())) {
    // do whatever
}
7 голосов
/ 24 августа 2016

Используйте ArrayUtils.nullToEmpty из библиотеки commons-lang для массивов

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

Эта функция существует в библиотеке commons-lang, которая включена в большинство проектов Java.

// 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;
}

Это то же самое, что и ответ, данный @OscarRyz, но ради мантры DRY , я думаю, это стоит отметить. См. Страницу проекта commons-lang . Вот документация nullToEmpty API и source

Запись Maven для включения commons-lang в ваш проект, если это еще не сделано.

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

К сожалению, commons-lang не предоставляет эту функциональность для List типов. В этом случае вам придется использовать вспомогательный метод, как упоминалось ранее.

public static <E> List<E> nullToEmpty(List<E> list)
{
    if(list == null || list.isEmpty())
    {
        return Collections.emptyList();
    }
    return list;
}
7 голосов
/ 12 февраля 2010

Если вы получаете это List из вызова метода, который вы реализуете, то не возвращайте null, возвращайте пустое List.

Если вы не можете изменить реализацию, то вы застряли с проверкой null. Если это не должно быть null, то выдается исключение.

Я бы не стал использовать вспомогательный метод, который возвращает пустой список, потому что он может быть полезен иногда, но тогда вы привыкнете вызывать его в каждом цикле, который вы делаете, возможно, скрывая некоторые ошибки.

4 голосов
/ 13 августа 2015

Я изменил приведенный выше ответ, поэтому вам не нужно приводить из Объекта

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

, а затем просто вызвать список по

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

Explaination: MyOwnObject: если List<Integer>, тогда MyOwnObject будет Integer в этом случае.

1 голос
/ 14 сентября 2016

Для тех, кто не заинтересован в написании собственного метода защиты от статического нуля, вы можете использовать: commons-lang's org.apache.commons.lang.ObjectUtils.defaultIfNull(Object, Object) Например:

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

ObjectUtils.defaultIfNull JavaDoc

1 голос
/ 29 августа 2013

Еще один способ эффективно защититься от нулевого значения в цикле for - это обернуть вашу коллекцию с помощью Google Guava Optional<T>, поскольку, как мы надеемся, это делает возможность фактически пустой коллекции ясной, поскольку клиент можно было бы проверить, присутствует ли коллекция с Optional.isPresent().

0 голосов
/ 03 ноября 2017

Используйте, CollectionUtils.isEmpty(Collection coll) метод, который является нулевой безопасной проверкой, если указанная коллекция пуста.

для этого import org.apache.commons.collections.CollectionUtils.

Зависимость Maven

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>
...