Узнайте, какая переменная бросает NullPointerException программным образом
Я знаю, что могу узнать, является ли переменная нулевой в Java, используя следующие методы:
- если
(var==null)
→ слишком много работы
-
try { ... } catch (NullPointerException e) { ...}
→ он сообщает мне, какая строка бросает исключение
- с помощью отладчика → вручную, слишком медленно
Рассмотрим эту строку кода:
if (this.superSL.items.get(name).getSource().compareTo(VIsualShoppingList.Source_EXTRA)==0) {
Я хотел бы знать, есть ли общий способ узнать, какая переменная (а не только строка) бросает исключение NullPointerException в определенной области кода. В этом примере, зная, что
Ответы
Ответ 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);
}