Подтвердить что ты не робот

Конструктор Java 7

Я увидел, что в Java 7 они внедрили метод Objects.requireNonNull(T obj, String message).

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

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

 public Foo(Bar bar, Baz baz) {
         /** Old one
         this.bar = bar;
         this.baz = baz;
         **/
         this.bar = Objects.requireNonNull(bar, "bar must not be null");
         this.baz = Objects.requireNonNull(baz, "baz must not be null");
   }

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

Или я должен оставить его как конструктор "классический/старый"?

4b9b3361

Ответ 1

Как вы можете видеть, есть несогласие в том, следует ли выбросить NPE или какое-либо другое исключение 1.

Если вы согласны с тем, что NPE более уместен, чем альтернативы, И это ситуация, когда null однозначно неверна, а затем:

  • лучше выбросить NPE раньше; т.е. в конструкторе, и
  • лучше бросить его с помощью специального сообщения об исключении; то есть не a null, как это происходит, когда JVM выбрасывает NPE.

В этом контексте использование Objects.requireNonNull является, безусловно, хорошей практикой.


Вы также можете использовать утверждения Java для этого, но вам нужно будет судить о том, хорошо ли это или плохо, что тест можно отключить. Вы должны подумать о том, превосходит ли преимущество в производительности от ранней проверки, проблемы, которые могут быть вызваны не проверкой ранее. Например, предположим, что вы видите NPE в производстве с отключенными утверждениями... и вы не можете его диагностировать. Вы включаете утверждения? Будут ли утверждения изменять поведение кода? Будет ли это замедлять работу вашей системы (из-за множества других проверок подтверждения)? Возможно ли повторение ситуации, которая вызвала НЭС?

(Ошибки, связанные с потоками, часто "раз в сине-лунном" вещах, которые чрезвычайно сложно воспроизвести. Я бы сказал, что вам нужна информация для диагностики проблемы ЛЮБОЕ время, когда это происходит... не только тогда, у вас включена проверка утверждения.)


Возможно, имеет значение аргумент обратной совместимости. Однако, как правило, вы не пишете свой код для работы на старых платформах Java. Если у вас есть специальное требование для поддержки старых версий Java..., которые отличаются друг от друга. Но если это так, вы не должны делать свою разработку против API Java 7 вообще... поэтому ваш компилятор /IDE должен помечать класс Objects как ошибку компиляции.

(Ограничение себя только использованием старых API-интерфейсов, когда вам не нужно, чтобы ухудшить качество кода и сделать его "устаревшим" раньше. Весь смысл нового материала - упростить запись надежные/поддерживаемые приложения. Умышленно не использовать его... порочный. Представьте, если вы ограничились Java 1.1...)


1 - FWIW, я думаю, что NPE все в порядке. И NPE с сообщением более конкретный, чем (скажем) IllegalArgumentException, и там множество прецедентов в стандартных библиотеках классов Java для конструкторов и т.д., Которые документируются как метательные NPE. Кроме того, этот метод был явно разработан таким образом.

Ответ 2

Мне не нравится, что requireNonNull() выбрасывает NullPointerException. На мой взгляд, бросание классического IllegalArgumentException делает намерение более ясным. Можно использовать Assertions также с тем преимуществом, что они могут быть выборочно включены и выключены.

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

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

Чтобы привести пример, что происходит, когда контейнер Spring обнаруживает, что свойство @Required на управляемом bean не может быть введено и поэтому осталось NULL. Вы, разумеется, не получите NullPointerException с описательным сообщением об ошибке.

Вы получаете BeanCreationException, обернутый вокруг BeanInitializationException, дающий дополнительную информацию об переменной-члене, которая все еще NULL в достаточно описательном сообщении об ошибке, например: "Свойство" центр "требуется для bean" круга ".

Ответ 3

Если у вас есть сеттеры для bar и baz, вы должны сделать это в сеттерах:

public Foo(Bar bar, Baz baz) {
    setBar(bar);
    setBaz(baz);
}

public void setBar(Bar bar) {
    this.bar = Objects.requireNonNull(bar, "bar must not be null");
}

public void setBaz(Baz baz) {
    this.baz = Objects.requireNonNull(baz, "baz must not be null");
}

В противном случае метод, который вы показали, прекрасен.

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