Исключает ли Null Pointer исключение кода?

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

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

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

Ответ 1

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

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

Ответ 2

Я могу думать о том, что на самом деле одно использование навсегда ловит NullPointerException:

catch (NullPointerException) {
    ApplyPainfulElectricShockToProgrammer();
}

Ответ 3

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

В этом случае он ОК, чтобы его уловить, иначе нет.

Ответ 4

Это зависит.

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

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

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

Ответ 5

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

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

Ответ 6

Смешные

Я только что нашел что-то, что нельзя делать на работе:

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)

чтобы аннулировать значения...

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

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

Ответ 7

Это плохо, но он может создать оптимизированный байт-код.

Если Integer i больше не null, тогда проверка уменьшает общую производительность. Сам чек стоит 3 инструкции (0-4). Тогда весь случай принимает 7 инструкций (0-14).

public class IfNotNull {

    public Integer i;

    public String getIAsString() {
        if (i != null) {
            return i.toString();
        } else {
            return "";
        }
    }
}

  public java.lang.String getIAsString();
    Code:
       0: aload_0       
       1: getfield      #2                  // Field i:Ljava/lang/Integer;
       4: ifnull        15
       7: aload_0       
       8: getfield      #2                  // Field i:Ljava/lang/Integer;
      11: invokevirtual #3                  // Method java/lang/Integer.toString:()Ljava/lang/String;
      14: areturn       // <- here we go
      15: ldc           #4                  // String 
      17: areturn 

Следуя EAFP, который распространен в мире Python. Случай null будет дорогостоящим, но нам нужно всего 4 команды (0-7) для случая not null.

public class TryCatch {

    public Integer i;

    public String getIAsString() {
        try {
            return i.toString();
        } catch (NullPointerException npe) {
            return "";
        }
    }
}

  public java.lang.String getIAsString();
    Code:
       0: aload_0       
       1: getfield      #2                  // Field i:Ljava/lang/Integer;
       4: invokevirtual #3                  // Method java/lang/Integer.toString:()Ljava/lang/String;
       7: areturn       // <- here we go
       8: astore_1      
       9: ldc           #5                  // String a
      11: areturn       
    Exception table:
       from    to  target type
           0     7     8   Class java/lang/NullPointerException

Кто знает, может ли JIT-компилятор оптимизировать это?

Ответ 8

Это, безусловно, есть.

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

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

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

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

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

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

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

Ответ 9

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

Ответ 10

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

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

Конечно, я всегда получаю ровно одну строку внутри блока try. И еще, и я сам был бы виновен в плохом коде.

Ответ 11

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

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

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

х

Ответ 12

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

edit: в этом случае это обычно делается с помощью UncaughtExceptionHandler.

Ответ 13

Как насчет этого:

try
{
    foo.x = bar;
}
catch (NullPointerException e)
{
    // do whatever needs to be done
}

в качестве микро-оптимизации, когда foo может быть нулевым, но почти никогда не является?

Идея такова:

  • Явная проверка NULL принимает отдельную машинную инструкцию

  • С другой стороны, проверка NULL во второй версии может быть выполнена путем разрешения доступа к NULL, захвата SIGSEGV и выбрасывания исключения NullPointerException. Это бесплатно, если объект не равен NULL.

Ответ 14

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

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

Ответ 15

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

Ответ 16

Это действительно зависит от определения интерфейса. Неструктурированная обработка NPE так же плоха, как ловушка Exception или Throwable.

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

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

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

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

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

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

Ответ 17

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

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

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

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

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

Ответ 18

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

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