Лучшая практика в ловле и броске nullpointerexception? - PullRequest
5 голосов
/ 17 января 2011

Кажется, что это не очень хорошая идея, чтобы поймать nullpointerexception.Если это так, то почему это бросается методами?Должен ли он быть пойман с помощью Exception?

Кроме того, если я столкнусь с параметром, который имеет значение null (может быть примитивного типа, например, string или класс с полями), как мне его обработать?(предположительно не киньте npe)?

Спасибо

Ответы [ 7 ]

14 голосов
/ 17 января 2011

Это исключение времени выполнения , поэтому оно не предназначено для того, чтобы быть пойманным глубоко в программном коде, только [обновление] на (или близко к) верхнем уровне или [/ update] от JVM.Поскольку исключения во время выполнения сигнализируют о серьезных проблемах (как правило, о серьезных ошибках программирования, проблемах конфигурации / интеграции и т. Д.), Лучше всего позволить им распространяться на вершину, что обычно приводит к впечатляющему отказу всего потока.Это дает сильный сигнал о том, что что-то не так и должно быть исправлено КАК МОЖНО СКОРЕЕ.

См. Также Перехватывает ли исключение нулевого указателя запах кода? .

Кроме того, если я сталкиваюсь с параметром, который является пустым [...], как я должен обработать это?

Можно бросить NPE вообще.Однако, в зависимости от обстоятельств, вы также можете рассмотреть IllegalArgumentException или , используя утверждение .См. Также

6 голосов
/ 17 января 2011

Исключение nullpointerexception обычно указывает на ошибку программиста .Вы не поймаете исключение нулевого указателя, если не ожидаете такой ошибки программиста.Например, допустим, вы реализуете метод myMethod с одним параметром типа P.

void myMethod(P x)

Допустим, вы не ожидаете, что параметр x будет нулевым.В этом случае вы можете не проверять на ноль.Зачем?потому что вы предполагаете, что программист, который использует ваш метод, будет использовать его правильно и не будет принимать значение null.Я не говорю, следует ли вам проверять наличие нуля в таких случаях.Я просто пытаюсь ответить, почему иногда исключение пустого указателя генерируется методом и не должно быть перехвачено.И вот почему: ваш метод может выдать исключение нулевого указателя, потому что кто-то неправильно его использовал (передал нуль).Программист, который использует ваш метод, может знать, что, если метод используется неправильно, он может выдать nullpointerexcetption.Но даже если он использует ваш метод неправильно, исключение не будет поймано, потому что все предполагают, что метод не используется неправильно.

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

  • Бросить IllegalArgumentException указание параметра равно нулю, и ваш метод ожидает, что он не будет равен нулю.
  • Ничего не предпринимайте.Предположим, что ваш метод используется правильно (другими словами, не допускайте ошибок программиста).
  • Используйте утверждения : assert(x != null);

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

4 голосов
/ 17 января 2011

Этот ответ может быть длинным, но я думаю, что оно того стоит.

Кажется, что не очень хорошая идея поймать nullpointerexception.

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

Если это так, то почему это бросается методами? Должен ли он быть пойман с исключением?

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

Кроме того, если я сталкиваюсь с параметром, который является нулевым, как мне обращаться с ним? [...] (предположительно, не бросать npe)?

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

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

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

Например:

/**
* ...
* @param - OptionalMessage may be null, include anything else you wan to save.
*/
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   SomeMessage message = SomeMessage.createMessage();
   message.setHeader( c.name() );
   message.setCustomerInformation( c );
   if( optionalMessage != null ) { // is optional? handle it
      message.add( optionalMessage.status() );
      message.add( optionalMessage.summary() );
      message.add( optionalMessage.message() );
    }
 }

}

Вы подтверждаете наличие нуля и документируете его.

Но в этом же коде в качестве параметра также указан customer, в этом случае вы можете:

а) Ничего не делать b) Подтвердите также c) Создайте другое исключение в соответствии с уровнем абстракции на этом уровне.

Например, приведенный выше код ничего не делает a) . Это приведет к исключению NullPointerException, при котором вызывается код c.name(), и это следует отлавливать на ранних этапах тестов разработки. Кроме того, это должно быть задокументировано в параметре и бросках в javadoc.

/**
 * ...
 * @param  c - The customer whose information is to be sent. NotNull 
 * ...
 * @throws NullPointerException if the customer is null
 */
public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   SomeMessage message = SomeMessage.createMessage();
   ...

Если кто-нибудь вызовет этот метод с нулем, Npe укажет, что он что-то не так кодировал. Плюс, Npe, очень быстро скажет, что и где была ошибка кодирования (при вызове sendCustomerInformation с нулевым клиентом.

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

В этом случае вы можете проверить его и вернуться преждевременно ( я закончил способ)

public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  return; // I'm done! } 
   // else 
   SomeMessage message = ... 
   ..
}

Или может создать замену:

public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  c = new EmptyCustomer() ;} 
   // else 
   SomeMessage message = ... 
   ..
}

option c) Это похоже на a, но в этом случае вы выбрасываете исключение в соответствии с уровнем абстракции. Например, если это будет показано конечному пользователю в графическом интерфейсе или что-то еще, может не иметь смысла просто бросать Npe:

public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  
     // oh oh  something went wrong. 
     log.fatal("Invalid argument on \"sendCustomerInformation\" );
     throw new MyApplicationException("Dear customer, the information yada yaa"); 
   } 
   ...

Если это какое-то состояние инвалида в приложении:

public void sendCustomerInformation( Customer c , OptionalMessage optionalMessage ) { 
   if( cusomer == null ) {  
     // wait a minute, how could... why did.. what?
     throw new IllegalStateException("Hey, I got null on sendCustomerInformation and this shouldn't happen");
   }
   ...

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

Заключение

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

Надеюсь, это поможет.

См. Также: Исключение, отличное от RuntimeException

2 голосов
/ 17 января 2011

Бросьте исключение IllegalArgumentException, а не NP, если кто-то незаконно передает Null вашему методу. Это лучше описывает ошибку.

1 голос
/ 17 января 2011

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

1 голос
/ 17 января 2011

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

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

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

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

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

0 голосов
/ 17 января 2011

Чтобы избежать нулевых проверок в вашем коде, в большинстве случаев целесообразно возвращать нулевой объект или пустой список / карту / набор вместо нулевого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...