Существует, по крайней мере, 4 полностью различных последствий того, что делает ненулевая аннотация. Большинство аннотаций подразумевают только одну из этих разных вещей. Поэтому да, может иметь смысл применить более одной такой аннотации. К сожалению, фактическое значение этих аннотаций довольно запутано, потому что, по моему опыту, практически никто из разработчиков не учел тот факт, что они имеют в виду разные вещи; на самом деле большинство разработчиков, с которыми я встречался, совершенно не замечают тот факт, что аннулированные аннотации невероятно сложны и неопределенно определены.
Интерпретация системы типов («не может быть!»)
Эта интерпретация является утверждением типа, которое пытается быть таким же сильным, как String
в String x;
: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} *} *} * * * * * * * * * * * * * * * * * * * * * * * * * * *. невозможно, естественно, было бы совершенно бесполезной идеей проверить это. Учитывая это объявление, что-то вроде String z = (String) x
настолько бесполезно, что на самом деле это предупреждение компилятора.
Так же и с такой аннотацией. Примерами этого являются checkerframework, eclipse и intellij: org.checkerframeworkchecker.nullness.qual.NonNull
, org.jetbrains.annotations.NotNull
и eclipse's org.eclipse.jdt.annotation.NonNull
, все в основном подразумевают это значение (хотя intellij относится к параметрам и методам, тогда как checkerframework и eclipse являются аннотациями type_use. Я говорил вам это сложно: P).
Эти аннотации, подразумевающие «не может быть», используются для проверки во время записи. По той же причине написание String x = 5;
является немедленным , так как вы пишете этот код и еще до того, как сохраняете файл, красная волнистая линия подчеркивания в вашей IDE, как и, скажем, someMethod(map.get(key))
, где someMethod's параметр аннотируется одной из этих NonNull
аннотаций. Это не столько «вы не должны», это «вы не можете этого сделать; я даже не позволю вам».
Конечно, javac компилятор не на самом деле работают именно так, именно IDE и инструменты пытаются сделать так, чтобы это выглядело так. Точно так же, как если бы вы никогда не приводили переменную типа String к String, вы на самом деле не рассматриваете такие аннулирования аннулирования как подразумевающие необходимость проверки. Нет; значит: нет. Это подразумевает, что проверка уже выполнена, и вам не нужно проверять снова.
Конечно, это сложно: танцевать вокруг того факта, что компилятор java на самом деле остановит вас от нарушения смысла эти ненулевые аннотации ... некоторые инструменты (такие как kotlinc) в любом случае будут вставлять явные нуль-проверки. Немного похоже на то, как обобщенные значения могут заставить javac внедрять некоторые проверки типов в местах, где вы никогда не писали явное приведение, чтобы обойти тот факт, что обобщенные элементы являются дополнением времени компиляции для сохранения обратной совместимости. Идея состоит в том, чтобы рассмотреть эти детали реализации, о которых вам не следует думать.
Интерпретация БД
Когда hibernate использует класс в качестве шаблона для создания оператора CREATE TABLE
SQL Полезно иметь возможность использовать аннотации для установки ограничений и правил и т.п. По той же причине, по которой вы можете пометить поле следующим образом: «Превращая это в столбец SQL, скажите, чтобы механизм БД поместил в него уникальный индекс», вы можете пометить его как: «При превращении этого в в столбце SQL укажите механизму БД наложить на него ненулевое ограничение ".
Это относится к интерпретации системы типов, как к оружию и бабушке: у вас могут быть объекты, представляющие строки в БД, но которая не будет успешно сохранена из-за нарушения ограничения все время ; например, любое поле unid с автоматическим подсчетом обычно равно 0, и оно не будет таким образом сохраняться (механизм БД преобразует этот 0 в «не имеет значения; вставьте без него и позвольте последовательности механизма БД заполнить это число). Так же и с этими: это действительно ничего не значит для java; механизм SQL позаботится о том, чтобы указать, что вставка / обновление завершается неудачно из-за сбойного ограничения. Конечно, чтобы сохранить туда-обратно в БД и поскольку это просто не разрешено быть простым, большинство фреймворков БД будут иметь нулевую проверку, как вы называете эквивалентом .save()
или .store()
. Но это всего лишь ярлык для этого ограничения БД.
Интерпретация проверки
Иногда объекты в java представляют собой внешнюю вещь. Например, строка БД (частично совпадающая с предыдущим значением) или, скажем, веб-форма, представленная пользователем. Такие объекты ДОЛЖНЫ представлять точно фактическое состояние фактической внешней вещи, которую оно представляет. Бородавки и недопустимые гобелены и все такое.
И обычно у вас есть фреймворк, который позволяет вам проверить их. Вот что означало бы ненулевое значение проверки: это поле может быть нулевым, и если вы попытаетесь установить его в нулевое значение, исключений не будет (следовательно, они могут быть). Однако, пока это поле остается пустым, если вы спросите меня, является ли объект действительным, ответ будет таким: Нет.
Интерпретация ломбка
К сожалению, ломбок несколько мутит воду ... как и все остальные фреймворки. Что означает ломбок @NonNull
, зависит от того, где он появляется. Если для параметра это означает: Lombok, пожалуйста, сгенерируйте явную нулевую проверку в качестве первой строки в методе, если только я сам не написал это.
В полях это означает: "Ради @RequiredArgsConstructor
, Считайте это поле обязательным; проверьте его на null (сгенерировав исключение) в сгенерированном конструкторе. Также скопируйте аннотацию nullity, где это уместно, и, следовательно, если для этого поля сделан установщик ... добавьте эту nullcheck внутри. "
Ваш конкретный c case
Учитывая, что аннулированные аннотации означают совершенно разные вещи, поэтому потенциально не безумно применять более одной такой аннотации к одной и той же конструкции в вашем коде. Если вы хотите, чтобы механизм БД генерировал ограничение SQL NON NULL
, если этот класс используется в качестве шаблона, и для любого объекта, представляющего строку в этой таблице, немедленно отклонить любая попытка перевести его в недопустимое состояние, добавив оба, может иметь смысл. Если вы предпочитаете, чтобы объекты приемлемо представляли недопустимое состояние, что почти всегда имеет место, если общий принцип заключается в создании пустого объекта и затем установке каждого значения поля по одному с помощью установщика - тогда не добавляйте lombok's аннотация.
Конечно, вы рассмотрели всю сложность, верно?
Даже не проблеск. Для настоящего скручивания мозга рассмотрим checkerframework's @ PolyNull и посчитайте, что это упрощение того, с чем должна справиться настоящая система типов!
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я - ядро участник проекта Ломбок.