Действительно ли ловлей является исключение нулевого указателя запах кода?

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

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

Есть ли какие-либо случаи, где имеет смысл ловить исключение нулевого указателя?

57
задан Drew 6 April 2010 в 05:00
поделиться

15 ответов

Да, перехват любого RuntimeException почти всегда является запахом кода. C2 Wiki , похоже, согласен.

Исключением, вероятно, будут некоторые специально защитные фрагменты кода, которые запускают в значительной степени случайный код из других модулей. Примерами таких защитных структур могут быть EDT , ThreadPools / Executors и система плагинов.

36
ответ дан 7 November 2019 в 06:05
поделиться

Я стараюсь гарантировать результаты от моих интерфейсов, но если какая-то библиотека или чей-то код может в результате выдать null, и я ожидаю, что гарантия отлова может оказаться жизнеспособной. Конечно, что вы будете делать, когда поймаете это, зависит от вас. Иногда просто не имеет смысла проверять значение null, и если вы его поймаете, у вас есть другой метод решения проблемы, который может быть не таким хорошим, но выполняет свою работу.

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

0
ответ дан 7 November 2019 в 06:05
поделиться

Перехват исключения указателя NULL действительно зависит от контекста ... следует стремиться избегать строгих абсолютных правил ... правила должны применяться в контексте - нужно перехватить это исключение и перевести все программное обеспечение в какое-то СТАБИЛЬНОЕ состояние - выполнение ничего или почти ничего. Все такие правила кодирования должны быть хорошо поняты

На этом этапе вы затем посмотрите на свою программу AUDIT TRACE ... что вы должны делать, и обнаружите ИСТОЧНИК этого исключения.

Идея о том, что исключение указателя NULL никогда не должно возникать, должна быть проверяемой. Сначала выполните статический анализ ... (что сложнее, если есть сторонний код / ​​компоненты), а затем выполните исчерпывающий поиск в пространстве состояний с использованием соответствующих инструментов.

x

1
ответ дан 7 November 2019 в 06:05
поделиться

Это действительно зависит от определения интерфейса. Обработка неструктурированного NPE так же плоха, как перехват исключения или выброса.

Нулевые значения полезны для идентификации неинициализированного состояния вместо использования пустой строки, max_int или чего-то еще. Когда-то место, где я регулярно использую null, находится в местах, где объект обратного вызова не имеет значения.

Мне очень нравится аннотация @Nullable, предоставленная Guice.

http://code.google.com/docreader/#p=google-guice&s=google-guice&t=UseNullable

Чтобы исключить исключения NullPointerExceptions в базе кода, вы должны соблюдать дисциплину {{1} } о пустых ссылках. Нам удалось это сделать, следуя и применяя простое правило:

Каждый параметр не равен нулю, если явно не указан. В библиотеке Google Collections и JSR-305 есть простые API для получения нулей под управлением . Preconditions.checkNotNull может использоваться для быстрого отказа, если найдена пустая ссылка, а @Nullable может использоваться для аннотирования параметра, который разрешает нулевое значение.

Guice по умолчанию запрещает null. Он откажется вводить null, вместо этого выдаст исключение ProvisionException. Если значение null разрешено вашим классом, вы можете аннотировать поле или параметр с помощью @Nullable. Guice распознает любую аннотацию @Nullable, например edu.umd.cs.findbugs.annotations.Nullable или javax.annotation.Nullable.

0
ответ дан 7 November 2019 в 06:05
поделиться

Я могу придумать ровно одно использование для перехвата NullPointerException :

catch (NullPointerException) {
    ApplyPainfulElectricShockToProgrammer();
}
24
ответ дан 7 November 2019 в 06:05
поделиться

Да, в Java необходимо проверить исключение NullPointerException.

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

Вызов метода экземпляра нулевого объекта. Доступ или изменение поля нулевого объекта. Принимая длину нуля, как если бы это был массив. Доступ или изменение пустых слотов, как если бы это был массив. Выбрасывание null, как если бы это было значение Throwable.

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

NullPointerException на других языках при чтении текстовых файлов (например, XML), записи которых не были проверены на правильный символ ASCII и формат записи.

0
ответ дан 7 November 2019 в 06:05
поделиться

Давным-давно у меня было одно применение. Особенно глупая библиотека выбрасывала NullPointerException при запросе объекта в коллекции по ключу, а объект не был найден. Не было другого способа поиска, кроме как по ключу, и не было способа проверить, существует ли объект.

Через некоторое время мы загрузили производителя и начали модифицировать библиотеку. Теперь библиотека выбрасывает лучшее исключение (мое изменение) и имеет функцию проверки (чужое изменение).

Конечно, в итоге я всегда получал ровно одну строчку внутри блока try. Больше - и я сам буду виновен в плохом коде.

1
ответ дан 7 November 2019 в 06:05
поделиться

Единственное место, где вы должны перехватывать исключение NullPointerException (или, в частности, любой Throwable), - это верхний уровень или граница системы, чтобы ваша программа не завершилась полностью и могла восстановиться. . Например, настройка страницы с ошибкой в ​​вашем web.xml обеспечивает всеохватывающее, чтобы веб-приложение могло восстановиться после исключения и уведомить пользователя.

2
ответ дан 7 November 2019 в 06:05
поделиться

Это зависит от обстоятельств.

Насколько опытен этот сотрудник? Он делает это из-за незнания / лени или для этого есть веская причина? (например, это главный поток над всем остальным, и он никогда не должен умирать?)

В 90% случаев обнаружение исключения времени выполнения неверно, в 99% случаев обнаружение исключения NullPointerException неверно (если причина «Я был получить их много ... " тогда весь программист ошибается, и вы должны внимательно следить за остальной частью кода, который он делает)

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

7
ответ дан 7 November 2019 в 06:05
поделиться

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

В этом случае нормально поймать его, в противном случае - нет.

15
ответ дан 7 November 2019 в 06:05
поделиться

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

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

3
ответ дан 7 November 2019 в 06:05
поделиться

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

0
ответ дан 7 November 2019 в 06:05
поделиться

Перехват NPE (фактически любых RTE) может потребоваться для полного завершения приложения на основе Swing-GUI.

править: в этом случае обычно это делается через UncaughtExceptionHandler.

1
ответ дан 7 November 2019 в 06:05
поделиться

Забавно

Я только что нашел то, что не следует делать на работе:

public static boolean isValidDate(final String stringDateValue) {
    String exp = "^[0-9]{2}/[0-9]{2}/[0-9]{4}$";
    boolean isValid = false;
    try {
        if (Pattern.matches(exp, stringDateValue)) {
            String[] dateArray = stringDateValue.split("/");
            if (dateArray.length == 3) {
                GregorianCalendar gregorianCalendar = new GregorianCalendar();
                int annee = new Integer(dateArray[2]).intValue();
                int mois = new Integer(dateArray[1]).intValue();
                int jour = new Integer(dateArray[0]).intValue();

                gregorianCalendar = new GregorianCalendar(annee, mois - 1,
                        jour);
                gregorianCalendar.setLenient(false);
                gregorianCalendar.get(GregorianCalendar.YEAR);
                gregorianCalendar.get(GregorianCalendar.MONTH);
                gregorianCalendar.get(GregorianCalendar.DAY_OF_MONTH);
                isValid = true;
            }
        }
    } catch (Exception e) {
        isValid = false;
    }
    return isValid;
}

baaad :)

Разработчик хотел, чтобы календарь вызывал исключения такого рода:

java.lang.IllegalArgumentException: DAY_OF_MONTH
    at java.util.GregorianCalendar.computeTime(GregorianCalendar.java:2316)
    at java.util.Calendar.updateTime(Calendar.java:2260)
    at java.util.Calendar.complete(Calendar.java:1305)
    at java.util.Calendar.get(Calendar.java:1088)

для признания значений недействительными...

Да, это работает, но это не очень хорошая практика...

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

3
ответ дан 7 November 2019 в 06:05
поделиться

Несомненно.

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

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

Оператор if требует для выполнения, возможно, трех инструкций и является локальной проверкой (то есть вы выполняете проверку в том же месте, где вам нужна гарантия).

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

try
  return contacts.find("Mom").getEmail()
catch (NullPointerException e)
  return null

Вы не знаете, был ли NPE добавлен в 'getEmail' или в 'find'.

Технически худшее решение очень, очень распространенного шаблона, написанного более запутанным способом? Это не ранг, но он определенно плохо пахнет: /

2
ответ дан 7 November 2019 в 06:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: