Общий код для проверки, является ли объект нулевым?

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

Что-то вроде этого:

public boolean isNull(Object Obj, String Path){
    // ... 
}

Путь примерно такой: A.getB().getC(). . .

поэтому A передается как объект, а метод isNull сначала вызывает getB(), проверяет, не является ли возвращенный объект null, затем вызывает getC() и так далее.


person M Ah    schedule 25.11.2015    source источник
comment
Поскольку вам придется анализировать путь, а затем использовать отражение для достижения этой довольно простой цели, любое решение будет каким угодно, только не оптимизированным. Обычно вам все равно не понадобится такая вещь, поскольку инварианты классов должны поддерживаться соответствующими классами.   -  person biziclop    schedule 25.11.2015
comment
Вопрос имеет прямой ответ: используйте отражение. Но я думаю, что проблема в том, что вы пытаетесь сделать защитное программирование для многих полей ваших классов, что приводит к странному дизайну.   -  person Luiggi Mendoza    schedule 25.11.2015
comment
Тогда ты будешь искать какое-то время. Вместо того, чтобы тратить на это свое время, я рекомендую вам научиться программировать с защитой и использовать то, что язык дает вам в качестве инструментов (например, Optional для ссылок, допускающих значение NULL).   -  person Kayaman    schedule 25.11.2015
comment
Переключитесь на язык, который поддерживает этот регистр. Попробуйте docs.groovy-lang.org/next/html. /документация/   -  person Jayan    schedule 25.11.2015
comment
@Jayan или используйте Optional и продолжайте использовать Ява. Тем не менее проблема за кулисами беспокоит меня больше, чем предоставление конкретного решения для этого.   -  person Luiggi Mendoza    schedule 25.11.2015
comment
Цель разработки программы состоит не в том, чтобы избегать исключений, а в том, чтобы обрабатывать их в правильной форме. Да, для этого можно использовать отражение, но как насчет других исключений, генерируемых программой, то есть деления на ноль или чего-то в этом роде.   -  person gersonZaragocin    schedule 25.11.2015
comment
@gersonZaragocin Это отличная практика - проверять ввод на достоверность перед его использованием, в том числе проверять, что вещи не являются null, и выдавать более конкретное исключение из неудавшегося предварительного условия, а не полагаться на что-то дальше по линии, выбрасывая НПЭ. Но если вам нужно сделать это на несколько уровней глубже, вероятно, что-то не так с вашим дизайном.   -  person biziclop    schedule 25.11.2015
comment
@biziclop на 100% согласен с этим. Что я пытаюсь показать ему, так это то, что если этот дизайн сохранится, другие виды исключений, сгенерированные программой, могут иметь тот же тип реализации, и это никогда не было бы желательно.   -  person gersonZaragocin    schedule 25.11.2015
comment
который может принимать любой объект в качестве входных данных и, возможно, путь -> какой путь? Является ли A тем же, что и параметр Obj (пожалуйста, используйте для них строчные буквы)?   -  person Mr_and_Mrs_D    schedule 25.11.2015
comment
Похоже, вы ищете нулевой оператор объединения, который не существует в Java. Он был предложен для включения в Java 7, но отклонен.   -  person dimo414    schedule 25.11.2015
comment
Парень Большое спасибо, помощь очень ценится. Я пытаюсь обойти ограничение цикломатической сложности PMD. на данный момент в текущем наборе правил установлено около 10, что дает очень мало места для добавления другой логики к методу, если объект должен быть утвержден NotNull перед его использованием. Отсюда и необходимость в этом. Кроме того, это крупномасштабное приложение, которое время от времени использует композицию объектов на нескольких уровнях. Я снова новичок в кодировании, надеюсь, я понимаю   -  person M Ah    schedule 30.11.2015
comment
Нравится идея... использование в java-потоках Stream.of(arr).filter(Object::isNotNull).forEach(...); кажется хорошим вариантом ее использования, к сожалению, его там нет. Но эта форма не является непостижимой: Stream.of(arr).filter(r->r != null).forEach(...); просто каждое использование потенциально приведет к новой ссылке на метод.   -  person YoYo    schedule 11.05.2018


Ответы (3)


В комментариях есть множество методов выделения, которые можно использовать, чтобы избежать null проверок.

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

public class NullCheck<T>
{
  private T root;

  public NullCheck(T root)
  {
    this.root = root;
  }

  public <C> NullCheck<C> with(Function<T, C> getter)
  {
    return root != null ? new NullCheck<>(getter.apply(root)) : new NullCheck<>(null);
  }

  public boolean isNull()
  {
    return root == null;
  }

  public boolean isNotNull()
  {
    return root != null;
  }
}

Что, учитывая Person, у которого есть Address с атрибутом zipCode, вы можете использовать NullCheck для написания такого кода:

if (new NullCheck<>(person).with(Person::getAddress).with(Address::getZipCode).isNotNull())
{
  ...
}
person Nick Holt    schedule 25.11.2015

Там есть несколько стратегий для проверки объектов null.

Вы можете использовать библиотеки Guava, чтобы проверить, является ли ссылка нулевой или не использует Предварительные условия API.

Проверьте документацию для проверки не null: http://google.github.io/guava/releases/snapshot/api/docs/com/google/common/base/Preconditions..html#checkNotNull(T)

На странице Guava Github есть интересная статья, объясняющая, как избежать null< /эм>.

Если вы используете Java 8, вы можете использовать необязательный, чтобы избежать постоянной проверки на null ссылки.

person Rafael Naufal    schedule 25.11.2015

Когда вы подготавливаете свой объект, вы можете поместить аннотацию @NotNull к имеющемуся у вас параметру, поэтому, когда вы его получите, у вас будет что-то еще, кроме нуля (если вы используете Java EE 6 и выше). Этот подход может быть довольно быстрым для выполнения каких-либо действий с получаемым объектом... Когда вы передаете null в качестве входных данных, вы получите исключение, для обработки которого требуется гораздо больше ресурсов и времени, чем просто проверка нуля.

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

private static final String NE_MESSAGE = "Object is null...";
private static final String NULL_LOG = "Value is null, param name: ";

public static boolean isNull(Strin name, Object... object) {
  for(Object o : object) {
      if ( o == null) {
          NullException ne = new NullException(NULL_MESSAGE);
          LOGGER.error(NULL_LOG + name);
          throw ne;
       }
     }
   return Boolean.FALSE;
}
person Franky    schedule 25.11.2015