Если вы пытаетесь выбрать между:
x = Repo.GetX(13);
try {
Services.Process(x);
} catch (NullPointerException) {
System.err.println('x is NULL');
}
или
x = Repo.GetX(13);
if (x != NULL) {
Services.Process(x);
} else {
System.err.println('x is NULL');
}
Тогда знайте, что они не означают одно и то же .Первый перехватывает any NullPointerException, выданное Process
.Второй обрабатывает только тот случай, когда x
сам по себе равен NULL - если Process
делает x.foo().bar()
, а x.foo()
возвращает NULL, он не обрабатывается.
Вы должны выбрать между двумяна какие ошибки вы можете справиться.
В случае, если Services.Process
задокументировано для выброса NullPointerException, если и только если x
равно NULL, так что (если мы верим в документацию) эти два значения означают одно и то же, тогда я бы сделалвторой.Таким образом, если документация ложная, и в Services.Process
есть ошибка, из-за которой она возникает в другой ситуации, мы не будем ошибочно обрабатывать / сообщать об исключении, как если бы x
были NULL, хотя на самом деле это не так.
Итак, поймайте и подавьте исключение в двух ситуациях:
- Вы знаете, что (такого рода вещи) вызвало ошибку, и вы знаете, что вы можете справиться с этой ситуацией и продолжить независимо.
- Для защиты некоторого довольно внешнего уровня кода, такого как цикл обработки событий, от непредвиденных ошибок в программе или среде.В идеале это должно привести к интенсивному ведению журнала, потому что либо система не смогла выполнить то, что вы ожидали (возможно, из-за нехватки ресурсов или неудовлетворенных зависимостей), либо в другом месте есть ошибка в чьем-то коде.
Не ловите только потому, что вы знаете одну ситуацию, которая может вызвать исключение, и справиться с этим, когда такое же исключение может быть вызвано по другим причинам.Я полагаю, что вы могли бы сделать:
x = Repo.GetX(13);
try {
Services.Process(x);
} catch (NullPointerException) {
if (x == NULL) {
System.err.println('x is NULL');
} else {
throw;
}
}
Но в данном случае это кажется мне ненужным многословным: поскольку мы можем заранее проверить, является ли x
нулем, мы могли бы также.Однако есть случаи, когда вы ловите исключение, потому что невозможно или просто глупо попытаться заранее предсказать, произойдет ли оно или нет:
String s = Rep.GetString(13);
try {
f = Float.parseFloat(s);
System.out.println('is a number');
} catch (NumberFormatException) {
System.out.println('not a number');
}
Мы могли бы проверить, является ли s
- это допустимое число перед вызовом parseFloat
, но в основном это будет выполнять ту же самую работу дважды - проверка строки на допустимое число с плавающей точкой во многом аналогична фактическому ее преобразованию.Поэтому имеет смысл перехватить это исключение - мы знаем, что это значит, мы знаем, что с этим делать, мы не могли бы реально предотвратить это.
(Или вы можете использовать DecimalFormat.parse, которыйне бросает вообще)