Подтвердить что ты не робот

Узнайте, какая переменная бросает NullPointerException программным образом

Я знаю, что могу узнать, является ли переменная нулевой в Java, используя следующие методы:

  • если (var==null) → слишком много работы
  • try { ... } catch (NullPointerException e) { ...} → он сообщает мне, какая строка бросает исключение
  • с помощью отладчика → вручную, слишком медленно

Рассмотрим эту строку кода:

if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0)  {

Я хотел бы знать, есть ли общий способ узнать, какая переменная (а не только строка) бросает исключение NullPointerException в определенной области кода. В этом примере, зная, что

4b9b3361

Ответ 1

Так как можно вызвать исключение нулевого указателя, даже не включив переменную:

throw new NullPointerException();

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

Лучше всего было бы поставить как можно меньше операторов на каждой строке, чтобы стало очевидно, что вызвало исключение нулевого указателя. Рассмотрим рефакторинг вашего кода в вопросе, чтобы выглядеть примерно так:

List items = this.superSL.items;
String name = items.get(name);
String source = name.getSource();
if (source.compareTo(VIsualShoppingList.Source_EXTRA) == 0)  {
    // ...
}

Это больше строк кода. Но это также более читаемо и более удобно.

Ответ 2

Извините, нет, нет простого программного способа определить, какая переменная или вызов метода является источником исключения. Вы можете использовать что-то вроде Aspect-Oriented Programming (AOP), например. AspectJ, но это не свойственно языку и обычно не включается в программу просто для целей отладки.

  • if (var==null) -> too much work
  • try { } catch() { }
  • Debugger

Я знаю, что вы не хотите это слышать, но это просто затраты на ведение бизнеса.

if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0)  {

Необычно видеть так много назовённых вызовов методов. Я считаю, что вам лучше всего привыкнуть к их разлому - не нужно до 1 вызова на линию, но меньше этого. Почему?

1) Correctness - действительно ли в проекте для одного из этих вызовов вернуть null? Если это так, вы должны разбить его, проверить и соответствующим образом обработать.

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

3) Efficiency - обычно, когда вы так глубоко входите в график (строя последовательность вызовов методов), вероятно, вам придется вернуться туда позже. Захват этого промежуточного значения в промежуточной переменной означает отказ от повторного вызова одного или нескольких методов.

4) Debugging - как указывает ваш вопрос, разбиение сложной строки, подобной этой, упрощает отладку. путем сужения возможного источника исключения.

Ответ 3

Что вы подразумеваете под "использованием отладчика → вручную, слишком медленно"? Если ваш код правильно структурирован, то не более двух или трех переменных, используемых в одной строке. Это так медленно, чтобы проверить их? У вас нет NullPointers каждую минуту.

Ответ 4

Я знаю, что вы предположили, что (var==null) - это слишком много работы, но, как заявил Мигель в комментариях, это то, с чем я бы пошел.

Ответ 5

Я думаю, вы должны заметить Закон о Деметрах.

Немногие люди следуют за ним строго, потому что это приводит к множеству методов делегатов.
Но слишком далеко от этого приведет к зависимостям от внутренних структур, которые должны быть прозрачными.

Ответ 6

К сожалению, Java не покажет вам имя переменной или точную позицию ошибки, отличной от номера строки. Если вы используете Eclipse, вы можете использовать аннотации с нулевыми значениями, например, см. http://www.fosslc.org/drupal/content/bye-bye-npe. См. Какую @NotNull аннотацию Java я должен использовать? для других систем аннотаций.

Ответ 7

То, что отлично поработало со мной, - это ловить исключение, где его обычно бросают, а затем использовать Log, чтобы узнать, имеют ли какие-либо из них значения "null".

Мой код:

 try {
                 if (description_visible) advice_title_cur.setText(all_title_array[pos]);
                 else advice_title_cur.setText(all_title_array[pos] + "...");

             } catch (NullPointerException e) {
                 e.printStackTrace();
                 Log.e("My name", "description_visible " + description_visible);
                 Log.e("My name", "advice_title_cur " + advice_title_cur);
                 Log.e("My name", "all_title_array " + all_title_array);
                 Log.e("My name", "pos " + pos);
             }