Распаковка Null-Object в тип примитива приводит к NullPointerException, хорошо? - PullRequest
36 голосов
/ 04 марта 2010

Этот фрагмент кода выдает NullPointerException из-за того, что он распакован в примитивный тип и называется Long.longValue(), верно?

Это даже легко увидеть, если у вас есть такой фрагмент кода:

long value = (Long) null;

Но NullPointerException еще сложнее попасть в более сложную ситуацию, такую ​​как:

long propertyValue = (Long) obj.getProperty(propertyModel.getName());

Так нет ли возможности для Java-компилятора сделать из этого более комфортное исключение? Я бы предпочел IllegalArgumentException с сообщением типа «Вы пытаетесь преобразовать нулевой объект в примитивный тип, это невозможно сделать!»

Разве это не было бы более уместным? Как вы думаете? Это вообще возможно во время выполнения? Можем ли мы определить этот состав? Я еще не посмотрел на байт-код Java. Может быть, это можно использовать в решении.

На этот вопрос можно ответить : Я хотел бы знать, возможно ли добиться такого поведения!

Ответы [ 4 ]

69 голосов
/ 04 марта 2010

В соответствии с спецификацией языка Java , распаковка происходит через вызовы Number.longValue(), Number.intValue() и т. Д. Никакого особого волшебства байт-кода не происходит, это точно так же, как если бы вы вызывали эти методы вручную , Таким образом, NullPointerException является естественным результатом распаковки null (и фактически обязанным JLS).

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

9 голосов
/ 23 ноября 2017

Начиная с Java 8 SE также имеется Option.ofNullable

long value = Optional.ofNullable(obj.getProperty(propertyModel.getName())).orElse(0L)));
1 голос
/ 16 октября 2013

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

Хорошо поместить достаточно «состояния» операции в исключение (в этом случае имя опции и значение - возможно, даже строковое представление карты опций, если она не найдена).

Что-то вроде:

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 и исключения исключений или соглашения о ведении журнала рассматриваемого приложения. Трудно сделать это универсальным.

1 голос
/ 04 марта 2010

Это не то, что означает IllegalArgumentException. Компилятор не гарантирует, что значение будет null до времени выполнения. Все, что он знает, это тип, который в вашем примере, вероятно, будет String.

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

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