Unboxing Null-Object для длительных результатов в NullPointerException, отлично?
Этот фрагмент выдает NullPointerException
из-за того, что его unboxed на примитивный тип и Long.longValue()
вызывается, правильно?
Это даже легко увидеть, если у вас есть такой сниппет:
long value = (Long) null;
Но NullPointerException
еще сложнее попасть в более сложную ситуацию следующим образом:
long propertyValue = (Long) obj.getProperty(propertyModel.getName());
Итак, нет ли возможности для Java-Compiler сделать из этого более комфортным Исключение? Я бы предпочел IllegalArgumentException
с сообщением типа "Вы пытаетесь применить null-Object в примитивный тип, это невозможно!"
Разве это не было бы более уместным? Как вы думаете? Возможно ли это во время выполнения? Можем ли мы определить этот актерский состав? Я еще не посмотрел на java-байт-код. Возможно, он может быть использован в решении.
На этот вопрос можно ответить. Я хотел бы знать, возможно ли достичь такого поведения!
Ответы
Ответ 1
В соответствии с спецификацией языка Java, unboxing происходит через вызовы Number.longValue()
, Number.intValue()
и т.д. Нет специальной магии байтового кода Это точно так же, как если бы вы вызывали эти методы вручную. Таким образом, NullPointerException
является естественным результатом распаковки a null
(и, по сути, JLS).
Для исключения другого исключения потребуется проверка для null
дважды во время каждого преобразования unboxing (один раз, чтобы определить, нужно ли бросать специальное исключение и некогда неявно, когда метод фактически вызывается). Я полагаю, что разработчики языка не считали это достаточно полезным, чтобы гарантировать это.
Ответ 2
Это не то, что означает IllegalArgumentException
. Компилятор не гарантирует, что значение будет null
до времени выполнения. Все, что он знает, это тип, который в вашем примере, вероятно, будет String
.
Конечно, во время выполнения, когда генерируется исключение, компилятор знает, что проблема - это значение null
. Вы сами это видите, если используете отладчик. Итак, с технологической точки зрения - и вот короткий ответ на ваш вопрос - да, было бы возможно создать компилятор, который будет включать это в описание ошибки. Но если вам нужно специальное сообщение для значений null
, что дальше? Специальные сообщения для целых чисел, которые находятся за пределами допустимой границы более чем на 10? По общему признанию, это глупый пример, но я надеюсь, что это иллюстративно.
Ответ 3
Это хорошая идея написать небольшой частный помощник для подобных случаев. Они могут обрабатывать корректные слежки, сообщения об ошибках и значения по умолчанию.
Хорошо добавить достаточное "состояние" операции в исключение (в этом случае имя опции и значение - возможно, даже строковое представление карты опций, если не найдено).
Что-то вроде:
private long safeGetLong(Map<String, Option> options, String name) {
if (name == null || options == null)
throw new IllegalArgumentExcption("You need to give options and name. (name="+name+", opts=" + options));
Object val = options.get(name);
if (val == null)
throw new ConfigurationException("The option name="+name+" is unknown");
if (val instanceof Long)
return val.longValue();
String strVal = null;
try
{
strVal = val.toString();
return Long.parseValue(strVal);
} catch (Exception ex) {
throw new ConfigurationException("Cannot parse " + name + "=" + strVal + " into a Long.");
}
}
Конечно, наличие объекта конфигурации, который позволяет типизировать доступ, еще лучше.
Существуют некоторые рамки проверки, которые могут сделать это для вас, но я, как правило, в конечном итоге пишу код сам по себе, так как он лучше вписывается в IN8L, а также в исключения из иерархии или протоколирования приложений, о которых идет речь. Трудно сделать этот общий.
Ответ 4
Так как Java 8 SE также есть Optional.ofNullable
long value = Optional.ofNullable(obj.getProperty(propertyModel.getName())).orElse(0L)));