Избегать! = Нулевые заявления - PullRequest
3805 голосов
/ 07 ноября 2008

Я использую object != null много, чтобы избежать NullPointerException.

Есть ли хорошая альтернатива этому?

Например:

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

Это позволяет избежать NullPointerException, когда неизвестно, является ли объект null или нет.

Обратите внимание, что принятый ответ может быть устаревшим, см. https://stackoverflow.com/a/2386013/12943 для более позднего подхода.

Ответы [ 62 ]

1 голос
/ 17 ноября 2015

Можно определить методы util, которые обрабатывают вложенные нулевые проверки почти симпатичным способом с лямбдами Java 8.

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

(Этот ответ был впервые опубликован здесь .)

0 голосов
/ 15 мая 2019

Другая альтернатива проверке! = Null (если вы не можете избавиться от нее по проекту):

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

или

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

С SomeClass, являющимся типом someobject.

Вы не можете получить возвращаемое значение из doCalc (), тем не менее, поэтому полезно только для методов void.

0 голосов
/ 03 января 2019

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

    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 голосов
/ 21 августа 2018

Kotlin с нулевой безопасностью - элегантная альтернатива, но это означает большее изменение.

0 голосов
/ 20 мая 2010

Для служебных классов вы можете проверить, что параметры не равны нулю.

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

0 голосов
/ 27 декабря 2017

Один вариант у вас есть

  • Использовать среду проверки @RequiresNonNull для методов. Например, вы получаете это, если вызываете метод, аннотированный как таковой, с нулевым аргументом. Это не удастся во время компиляции, даже до запуска вашего кода! так как во время выполнения это будет NullPointerException

    @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);
    
    }
    

получает

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

Существуют и другие методы, такие как «Использовать» в Java 8 «Необязательно», «Аннотации Guava», «Шаблон нулевого объекта» и т. Д. Неважно, если вы достигнете своей цели избегания!

0 голосов
/ 17 февраля 2011

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

Например, вместо функций, которые возвращают строки, возвращающие ноль, когда есть проблема (скажем, преобразование числа в строку), пусть они возвращают пустую строку (""). Вы все еще должны проверить возвращаемое значение, прежде чем продолжить, но не будет особых случаев для исключений. Дополнительным преимуществом этого стиля программирования является то, что ваша программа сможет дифференцировать и реагировать соответственно между обычными операциями и исключениями.

0 голосов
/ 28 декабря 2014

Скачать Groovy , настроить Groovy, загрузить плагин Groovy Eclipse и изменить файл .java на file.groovy. Тогда:

     String u;
     if (u) {
     } //Cast auto to false,
     else {
     }

Так же, как PHP / JavaScript . Затем продолжайте программировать на обычном Java, и это Java ++.

0 голосов
/ 28 августа 2017

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

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

Не будет выбрасывать исключение нулевого указателя

0 голосов
/ 23 ноября 2014

Вот мой подход ..

class MyObjectHandler
{
public static final int EXCEPTION = (-3);
public static final int INACCESSIBLE = (-2);

public static int doSomething (MyObject obj, MyObjectParameter [] input)
{
    int returnValue= 0;

    try
    {
        if (obj != null)
        {
            returnValue = obj.doSomething(input);
        }
        else
        {
            returnValue = MyObjectHandler.INACCESSIBLE;
        }
    }
    catch (Exception e)
    {
        e.printStack();
        returnValue = MyObjectHandler.EXCEPTION;
    }
    finally
    {
        return returnValue;
    }
}

..

}

Тогда ваш код будет выглядеть так:

import xx.xx.xx.MyObjectHandler;
import xx.xx.xx.MyObjectParameter;

class Test
{

    public static void main ()
    {

        MyObject obj = null;

        MyObjectHandler.doSomething(obj, null);

    }

    ..

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...