Зачем мне использовать Lombok-Annotation @NonNull?

Ломбок предлагает аннотация@NonNull, который выполняет проверку нуля и выдает NPE (если не настроено по-другому).

Я не понимаю, почему я буду использовать эту аннотацию, как описано в пример этой документации:

private String name;
public NonNullExample(@NonNull Person person) {
    super("Hello");
    if (person == null) {
      throw new NullPointerException("person is marked @NonNull but is null");
    }
    this.name = person.getName();
  }

NPE в любом случае будет брошен. Единственная причина, по которой здесь можно использовать аннотацию imo, заключается в том, что вы хотите, чтобы исключение отличалось от NPE.

Обновлено: я знаю, что исключение будет выбрано явно и, следовательно, «контролируется», но, по крайней мере, текст сообщения об ошибке должен быть редактируемым, не так ли?

рассмотрим пример. вы разрабатываете API, а поле помечено как @NonNull. когда когда-либо соответствующий json попадает в серверный API, он выдает НПЭ на уровне контроллера вместо прохождения через код, что также известно как fail-fast, а другие вещи зависят от варианта использования.

bananas 24.06.2019 13:08

Я думаю, что пример предназначен для демонстрации кода генерируется, если вы кодируете аннотацию @NonNull (отсюда и заголовок Ванильная Ява).

Jos 24.06.2019 13:20

@ Джос, это может быть правильным предположением. Это бы действительно объяснило, почему на некоторых страницах документации (1, 2) аннотации ломбока в valinna Java убирают, а на других (на той NonNull) они их сохраняют — возможно, код генерируется именно таким образом (удаление аннотаций там и сохранение здесь ). Тогда единственный вопрос, почему они генерируют код такими разными способами.

Sasha 24.06.2019 13:26

Вы не должны больше использовать этот, а тот, что из docs.oracle.com/javaee/7/api/javax/validation/constraints/….

Xavier Bouclet 24.06.2019 15:43

@XavierBouclet, я могу ошибаться, я не очень разбираюсь в Java, но ИМХО они просто служат разным целям.

Sasha 24.06.2019 16:02

Кажется, ты прав. я думал они одинаковые

Xavier Bouclet 24.06.2019 16:06

@Саша Ломбок всегда их раздевает, кроме @NonNull. Причина в том, что nonnull является единственным, который служит для целей документации/инструмента lint. Все остальные аннотации ломбока этого не делают, и поэтому их можно удалить, как только ломбок сделает свое дело.

rzwitserloot 29.06.2019 12:58
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
12
7
14 637
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Идея аннотации состоит в том, чтобы избежать if (person == null) в вашем коде и сделать его чище.

Если проверка не добавлена ​​в код, NPE выбрасывается в любом случае.

metters 24.06.2019 13:03

да. если вы обратитесь person.xxxx сюда. но вы можете передать его функции и добраться до нее по линии. С аннотацией вы проверяете, если в начале и с чистым кодом.

Roee Gavirel 24.06.2019 13:16

@RoeeGavirel, if (person == null) throw new NullPointerException("person is marked @NonNull but is null") выполняется перед выполнением любого person.xxx или передачей person функции.

Sasha 24.06.2019 13:19

@Sashe - ДА, но наличие @NonNull делает if (person == null) излишним.

Roee Gavirel 24.06.2019 13:22

@RoeeGavirel, да, именно — и именно об этом вопрос Меттерса (зачем мы добавляем @NonNull, если сохраняем if (person == null)).

Sasha 24.06.2019 16:00

ИМХО, вы неправильно поняли эта страница документации.

Эта страница документации не подразумевает, на которой вам рекомендуется использовать как аннотации Lombok @NonNull, так и явные if (smth == null) throw …-подобные проверки одновременно (одним и тем же методом).

Он просто говорит, что такой код (назовем его код А):

import lombok.NonNull;

public class NonNullExample extends Something {
  private String name;

  public NonNullExample(@NonNull Person person) {
    super("Hello");
    this.name = person.getName();
  }
}

будет автоматически (внутренне) переведен Ломбоком в код, аналогичный тому, который указан в вопросе (назовем его код Б).

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

Обратите внимание, что код Б — это «ванильный код Java». Ожидается, что он не будет обработан Ломбоком во второй раз. Так что @NonNull в код Б — это просто аннотация, которая никак не влияет на поведение (по крайней мере, не с точки зрения Ломбока).

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

Хотя то, что вы говорите, не является неправильным, все же можно использовать аннотации ломбока без в их процессоре аннотаций. В равной степени возможно, что их пример по-прежнему решил аннотировать параметр как @NonNull исключительно для целей документации.

BeUndead 24.06.2019 13:10

@ user2478398, они не делают этого в другие страницы документации.

Sasha 24.06.2019 13:11

Автор Ломбок здесь: Нет, это не подделка. Причина, по которой пример «post lombok» по-прежнему имеет ненулевую аннотацию, заключается в том, что, в отличие от большинства других аннотаций ломбока, если вы деломбокируете этот код, мы оставляем аннотацию. Это потому, что, как сказал @mernst, аннотация @NonNull ТАКЖЕ служит документацией и « ввод для целей линтеров, чего не делает большинство других аннотаций ломбока. Пример показывает, что lombok сгенерирует нулевую проверку, и это все, что он делает.

rzwitserloot 29.06.2019 12:56

Он служит той же цели, что и

java.util.Objects requireNonNull()

или предварительные условия Гуавы. Это просто делает код более компактным и отказоустойчивым.

Ответ принят как подходящий

Написание аннотации типа, такой как @NonNull, служит нескольким целям.

  • Это документация: он передает контракт метода клиентам более кратким и точным способом, чем текст Javadoc.
  • Он включает проверка во время выполнения, то есть гарантирует, что ваша программа вылетит с полезным сообщением об ошибке (вместо того, чтобы сделать что-то еще хуже), если глючный клиент неправильно использует ваш метод. Lombok делает это за вас, не заставляя программиста писать проверку во время выполнения. ссылочный пример показывает два способа сделать это: с помощью одной аннотации @NonNull или с явной проверкой, написанной программистом. Версия «Vanilla Java» либо имеет опечатку (случайный @NonNull), либо показывает код после его обработки Lombok.
  • Он включает проверка во время компиляции. Такой инструмент, как Платформа проверки, гарантирует, что код нет рухнет во время выполнения. Такие инструменты, как NullAway, Склонен к ошибкам и FindBugs, являются эвристическими средствами поиска ошибок, которые предупредят вас о некоторых случаях неправильного использования null, но не дадут вам никаких гарантий.

Было бы неплохо, если бы можно было сказать ломбоку, что все NonNull по умолчанию, и аннотировать только параметры, допускающие значение NULL, а не наоборот...

Klesun 30.06.2020 10:10

Я люблю ломбок, но в этом случае (лично) я предпочитаю использовать аннотацию @Nonnull из javax.аннотация с Objects.requireNonNull из java.util.Объекты.

Использование ломбока таким образом делает код чище, но еще менее понятным и читаемым:

public Builder platform(@NonNull String platform) {
    this.platform = platform;
    return this;
}  

Этот метод вызывает NullPointerException (нет доказательств этого) и в зависимости передача нулевого аргумента при вызове метода не сообщается моей IDE (IntelliJ Ultimate 2020.1 EAP — последняя версия — с плагином lombok)


Поэтому я предпочитаю использовать аннотацию @Nonnull из javax.аннотация следующим образом:

public Builder platform(@Nonnull String platform) {
    this.platform = Objects.requireNonNull(platform);
    return this;
}

Код немного многословен, но понятнее, и моя IDE способна предупредить меня, если я передам нулевой аргумент при вызове метода!

Другие вопросы по теме