it-swarm.com.ru

Какую аннотацию @NotNull Java мне следует использовать?

Я пытаюсь сделать мой код более читабельным, а также использовать инструменты, такие как IDE проверка кода и/или статический анализ кода (FindBugs и Sonar), чтобы избежать исключений NullPointerExceptions. Многие инструменты кажутся несовместимыми с аннотацией @NotNull/@NonNull/@Nonnull, и перечисление их всех в моем коде было бы ужасно читать. Какие-нибудь предложения, какой из них является "лучшим"? Вот список эквивалентных аннотаций, которые я нашел:

  • javax.validation.constraints.NotNull
    Создано для проверки во время выполнения, а не для статического анализа.
    документация

  • edu.umd.cs.findbugs.annotations.NonNull
    Используется Findbugs статический анализ и, следовательно, Sonar (теперь Sonarqube )
    документация

  • javax.annotation.Nonnull
    Это может работать и с Findbugs, но JSR-305 неактивно. (См. Также: Каков статус JSR 305? ) источник

  • org.jetbrains.annotations.NotNull
    Используется IntelliJ IDEA IDE для статического анализа.
    документация

  • lombok.NonNull
    Используется для управления генерацией кода в Project Lombok .
    Заполнение аннотации, так как нет стандарта.
    источник , документация

  • Android.support.annotation.NonNull
    Аннотация маркера, доступная в Android, предоставляется пакетом поддержки-аннотации
    документация

  • org.Eclipse.jdt.annotation.NonNull
    Используется Eclipse для статического анализа кода
    документация

860
jaxzin

Поскольку Oracle решил не стандартизировать @NonNull (и @Nullable) на данный момент, боюсь, нет хорошего ответа. Все, что мы можем сделать, это найти прагматическое решение, и мое следующее:

Синтаксис

С чисто стилистической точки зрения я хотел бы избегать любых ссылок на IDE, фреймворк или любой инструментарий, кроме Java.

Это исключает:

  • Android.support.annotation
  • edu.umd.cs.findbugs.annotations
  • org.Eclipse.jdt.annotation
  • org.jetbrains.annotations
  • org.checkerframework.checker.nullness.qual
  • lombok.NonNull

Что оставляет нам либо javax.validation.constraints, либо javax.annotation. Бывший поставляется с JEE. Если это лучше, чем javax.annotation, которая может в конечном итоге прийти с JSE или никогда вообще, это вопрос дискуссии. Я лично предпочитаю javax.annotation, потому что мне не нравится зависимость от JEE.

Это оставляет нас с

javax.annotation

который также самый короткий.

Существует только один синтаксис, который был бы даже лучше: Java.annotation.Nullable. Поскольку другие пакеты в прошлом переходили от javax к Java, javax.annotation был бы шагом в правильном направлении.

Реализация

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

Сначала за сходство:

Аннотации @NonNull имеют строку

public @interface NonNull {}

кроме

  • org.jetbrains.annotations, который называет его @NotNull и имеет тривиальную реализацию
  • javax.annotation, которая имеет более длинную реализацию
  • javax.validation.constraints, который также называет его @NotNull и имеет реализацию

Аннотации @Nullable имеют строку

public @interface Nullable {}

за исключением (снова) org.jetbrains.annotations с их тривиальной реализацией.

Для различий:

Поразительным является то, что

  • javax.annotation
  • javax.validation.constraints
  • org.checkerframework.checker.nullness.qual

у всех есть аннотации времени выполнения (@Retention (RUNTIME), в то время как

  • Android.support.annotation
  • edu.umd.cs.findbugs.annotations
  • org.Eclipse.jdt.annotation
  • org.jetbrains.annotations

только время компиляции (@Retention (CLASS)).

Как описано в этот SO ответ влияние аннотаций во время выполнения меньше, чем можно подумать, но они имеют то преимущество, что позволяют инструментам выполнять проверки во время выполнения в дополнение к тем, которые выполняются во время компиляции ,.

Другим важным отличием является где в коде аннотации могут быть использованы. Есть два разных подхода. Некоторые пакеты используют контексты стиля JLS 9.6.4.1. Следующая таблица дает обзор:

 
 ПАРАМЕТР МЕТОДА ПОЛЯ LOCAL_VARIABLE 
 Android.support.annotation XXX 
 Edu.umd.cs.findbugs.annotations XXXX 
 Org.jetbrains.annotation XXXX 
 Ломбок XXXX 
 Javax.validation.constraints XXX 

org.Eclipse.jdt.annotation, javax.annotation и org.checkerframework.checker.nullness.qual используют контексты, определенные в JLS 4.11, что, на мой взгляд, является правильным способом сделать это.

Это оставляет нас с

  • javax.annotation
  • org.checkerframework.checker.nullness.qual

в этом раунде.

Код

Чтобы помочь вам сравнить дальнейшие детали, я перечислю код каждой аннотации ниже. Чтобы упростить сравнение, я удалил комментарии, импорт и аннотацию @Documented. (все они имели @Documented, за исключением классов из пакета Android). Я изменил порядок строк и полей @Target и нормализовал квалификации.

package Android.support.annotation;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER})
public @interface NonNull {}

package edu.umd.cs.findbugs.annotations;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
public @interface NonNull {}

package org.Eclipse.jdt.annotation;
@Retention(CLASS)
@Target({ TYPE_USE })
public @interface NonNull {}

package org.jetbrains.annotations;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
public @interface NotNull {String value() default "";}

package javax.annotation;
@TypeQualifier
@Retention(RUNTIME)
public @interface Nonnull {
    When when() default When.ALWAYS;
    static class Checker implements TypeQualifierValidator<Nonnull> {
        public When forConstantValue(Nonnull qualifierqualifierArgument,
                Object value) {
            if (value == null)
                return When.NEVER;
            return When.ALWAYS;
        }
    }
}

package org.checkerframework.checker.nullness.qual;
@Retention(RUNTIME)
@Target({TYPE_USE, TYPE_PARAMETER})
@SubtypeOf(MonotonicNonNull.class)
@ImplicitFor(
    types = {
        TypeKind.PACKAGE,
        TypeKind.INT,
        TypeKind.BOOLEAN,
        TypeKind.CHAR,
        TypeKind.DOUBLE,
        TypeKind.FLOAT,
        TypeKind.LONG,
        TypeKind.SHORT,
        TypeKind.BYTE
    },
    literals = {LiteralKind.STRING}
)
@DefaultQualifierInHierarchy
@DefaultFor({TypeUseLocation.EXCEPTION_PARAMETER})
@DefaultInUncheckedCodeFor({TypeUseLocation.PARAMETER, TypeUseLocation.LOWER_BOUND})
public @interface NonNull {}

Для полноты, вот реализации @Nullable:

package Android.support.annotation;
@Retention(CLASS)
@Target({METHOD, PARAMETER, FIELD})
public @interface Nullable {}

package edu.umd.cs.findbugs.annotations;
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
@Retention(CLASS)
public @interface Nullable {}

package org.Eclipse.jdt.annotation;
@Retention(CLASS)
@Target({ TYPE_USE })
public @interface Nullable {}

package org.jetbrains.annotations;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
public @interface Nullable {String value() default "";}

package javax.annotation;
@TypeQualifierNickname
@Nonnull(when = When.UNKNOWN)
@Retention(RUNTIME)
public @interface Nullable {}

package org.checkerframework.checker.nullness.qual;
@Retention(RUNTIME)
@Target({TYPE_USE, TYPE_PARAMETER})
@SubtypeOf({})
@ImplicitFor(
    literals = {LiteralKind.NULL},
    typeNames = {Java.lang.Void.class}
)
@DefaultInUncheckedCodeFor({TypeUseLocation.RETURN, TypeUseLocation.UPPER_BOUND})
public @interface Nullable {}

Следующие два пакета не имеют @Nullable, поэтому я перечислю их отдельно. У lombok довольно скучный @NonNull. В javax.validation.constraints @NonNull на самом деле является @NotNull и имеет длинную реализацию.

package lombok;
@Retention(CLASS)
@Target({FIELD, METHOD, PARAMETER, LOCAL_VARIABLE})
public @interface NonNull {}

package javax.validation.constraints;
@Retention(RUNTIME)
@Target({ FIELD, METHOD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Constraint(validatedBy = {})
public @interface NotNull {
    String message() default "{javax.validation.constraints.NotNull.message}";
    Class<?>[] groups() default { };
    Class<? extends Payload>[] payload() default {};
    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
    @Retention(RUNTIME)
    @Documented
    @interface List {
        NotNull[] value();
    }
}

Служба поддержки

По моему опыту, javax.annotation, по крайней мере, поддерживается Eclipse и Checker Framework из коробки.

Резюме

Моей идеальной аннотацией был бы синтаксис Java.annotation с реализацией Checker Framework.

Если вы не собираетесь использовать Checker Framework, то javax.annotation ( JSR-305 ) по-прежнему будет лучшим выбором. в настоящее время.

Если вы хотите совершить покупку в Checker Framework, просто используйте их org.checkerframework.checker.nullness.qual.


Источники

  • Android.support.annotation от Android-5.1.1_r1.jar
  • edu.umd.cs.findbugs.annotations from findbugs-annotations-1.0.0.jar
  • org.Eclipse.jdt.annotation от org.Eclipse.jdt.annotation_2.1.0.v20160418-1457.jar
  • org.jetbrains.nnotations из jetbrains-annotations-13.0.jar
  • javax.annotation из gwt-dev-2.5.1-sources.jar
  • org.checkerframework.checker.nullness.qual из checker-framework-2.1.9.Zip
  • lombok от lombok commit f6da35e4c4f3305ecd1b415e2ab1b9ef8a9120b4
  • javax.validation.constraints из validation-api-1.0.0.GA-sources.jar
122
Ludwig Weinzierl

Мне очень нравится Checker Framework , который представляет собой реализацию аннотаций типов ( JSR-308 ), которая используется для реализации средств проверки дефектов, таких как средство проверки на нулевое значение. На самом деле я не пробовал других предлагать какое-либо сравнение, но я доволен этой реализацией.

Я не связан с группой, которая предлагает программное обеспечение, но я фанат.

Четыре вещи, которые мне нравятся в этой системе:

  1. У него есть дефекты для nullness (@Nullable), но есть и для неизменяемость и interning (и другие). Я использую первое (нулевое значение) и пытаюсь использовать второе (неизменность/IGJ). Я пробую третий, но пока не уверен, что буду использовать его в долгосрочной перспективе. Я еще не убежден в общей полезности других контролеров, но приятно знать, что сама структура представляет собой систему для реализации множества дополнительных аннотаций и контролеров.

  2. настройка по умолчанию для проверки нулевого значения работает хорошо: ненулевое значение, кроме локальных (NNEL). В основном это означает, что по умолчанию средство проверки обрабатывает все (переменные экземпляра, параметры метода, универсальные типы и т.д.), За исключением локальных переменных, как если бы они имели тип @NonNull по умолчанию. Согласно документации:

    Значение по умолчанию NNEL приводит к наименьшему количеству явных аннотаций в вашем коде.

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

  3. Этот каркас позволяет использовать с без создания зависимости от каркаса, приложив свои комментарии в комментарии: например, /*@Nullable*/. Это хорошо, потому что вы можете аннотировать и проверять библиотеку или общий код, но при этом иметь возможность использовать эту библиотеку/общую кодировку в другом проекте, который не использует платформу. Это хорошая особенность. Я привык к его использованию, хотя сейчас я имею тенденцию включать Checker Framework во всех моих проектах.

  4. У фреймворка есть способ аннотировать API вы используете, которые еще не аннотированы для пустоты с помощью стаб-файлов.

85
Bert F

Я использую тот IntelliJ, потому что меня больше всего интересует то, что IntelliJ помечает вещи, которые могут создавать NPE. Я согласен, что расстраивает отсутствие стандартной аннотации в JDK. Ходят разговоры о его добавлении, он может превратиться в Java 7. В этом случае будет еще один на выбор!

52
Sam Barnum

Согласно список возможностей Java 7 аннотации типа JSR-308 откладываются до Java 8. Аннотации JSR-305 даже не упоминаются.

Есть немного информации о состоянии JSR-305 в приложение последней версии JSR-308. Это включает в себя наблюдение, что аннотации JSR-305 кажутся заброшенными. Страница JSR-305 также показывает его как "неактивный".

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


Фактически, JSR-308 не определяет какие-либо типы/классы аннотаций, и похоже, что они думают, что это выходит за рамки. (И они правы, учитывая существование JSR-305).

Однако, если JSR-308 действительно выглядит как превращение в Java 8, меня не удивит, если интерес к JSR-305 возродится. AFAIK, команда JSR-305 официально не отказалась от своей работы. Они просто молчали 2+ года.

Интересно, что Билл Пью (технический лидер JSR-305) - один из тех, кто стоит за FindBugs.

32
Stephen C

Для проектов Android вы должны использовать Android.support.annotation.NonNull и Android.support.annotation.Nullable. Эти и другие полезные аннотации для Android доступны в Библиотека поддержки .

От http://tools.Android.com/tech-docs/support-annotations :

Сама библиотека поддержки также была аннотирована этими аннотациями, поэтому как пользователь библиотеки поддержки Android Studio уже проверит ваш код и отметит потенциальные проблемы на основе этих аннотаций.

26
James Wald

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

Вот как применить @Nonnull ко всем классам, методам и полям по умолчанию. Смотрите https://stackoverflow.com/a/13319541/14731 и https://stackoverflow.com/a/9256595/14731

  1. Определить @NotNullByDefault
import Java.lang.annotation.Documented;
import Java.lang.annotation.ElementType;
import Java.lang.annotation.Retention;
import Java.lang.annotation.RetentionPolicy;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;


    /**
     * This annotation can be applied to a package, class or method to indicate that the class fields,
     * method return types and parameters in that element are not null by default unless there is: <ul>
     * <li>An explicit nullness annotation <li>The method overrides a method in a superclass (in which
     * case the annotation of the corresponding parameter in the superclass applies) <li> there is a
     * default parameter annotation applied to a more tightly nested element. </ul>
     * <p/>
     * @see https://stackoverflow.com/a/9256595/14731
     */
    @Documented
    @Nonnull
    @TypeQualifierDefault(
    {
        ElementType.ANNOTATION_TYPE,
        ElementType.CONSTRUCTOR,
        ElementType.FIELD,
        ElementType.LOCAL_VARIABLE,
        ElementType.METHOD,
        ElementType.PACKAGE,
        ElementType.PARAMETER,
        ElementType.TYPE
    })
    @Retention(RetentionPolicy.RUNTIME)
    public @interface NotNullByDefault
    {
    }

2. Добавьте аннотацию к каждому пакету: package-info.Java

@NotNullByDefault
package com.example.foo;

UPDATE: по состоянию на 12 декабря 2012 г. JSR 305 указан как "неактивный". Согласно документации:

JSR, который был признан Исполнительным комитетом "спящим", или тот, который достиг конца своей естественной жизни.

Похоже, JSR 308 превращает его в JDK 8, и хотя JSR не определяет @NotNull, сопровождающий Checkers Framework делает , На момент написания этой статьи плагин Maven не работал из-за этой ошибки: https://github.com/typetools/checker-framework/issues/18

18
Gili

Если кто-то просто ищет классы IntelliJ: вы можете получить их из репозитория maven с помощью

<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations</artifactId>
    <version>15.0</version>
</dependency> 
18
Bruno Eberhard

Eclipse также имеет свои аннотации.

org.Eclipse.jdt.annotation.NonNull

Смотрите на http://wiki.Eclipse.org/JDT_Core/Null_Analysis для деталей.

12
Horcrux7

Просто отметим, что API валидации Java (javax.validation.constraints.*) не поставляется с аннотацией @Nullable, что очень ценно в контексте статического анализа. Это имеет смысл для проверки bean-компонента во время выполнения, поскольку это значение по умолчанию для любого не примитивного поля в Java (то есть ничего для проверки/применения). Для заявленных целей следует взвесить альтернативы.

11
Ophir Radnitz

К сожалению, JSR 308 не добавит больше значений, чем этот локальный проект Not Null.

Java 8 не будет поставляться с единственной аннотацией по умолчанию или собственной структурой Checker. Подобно Find-bugs или JSR 305, этот JSR плохо поддерживается небольшой группой в основном академических команд.

Никакой коммерческой власти за этим нет, поэтому JSR 308 запускает EDR 3 (Ранняя проверка проекта в JCP) СЕЙЧАС, в то время как Java 8 должен быть отправлен менее чем за 6 месяцев: -O Похож на 310 btw. но в отличие от 308 Oracle теперь взял на себя ответственность за это от своих основателей, чтобы минимизировать вред, который он нанесет платформе Java.

Каждый проект, поставщик и академический класс, подобные тем, что стоят за Checker Framework и JSR 308, создадут собственную проприетарную аннотацию проверки.

Делать исходный код несовместимым на долгие годы, пока не будут найдены несколько популярных компромиссов и, возможно, добавлены в Java 9 или 10, или через фреймворки, такие как Apache Commons или Google Guava ;-)

7
Werner Keil

Android

Этот ответ является Android конкретным. Android имеет пакет поддержки, называемый support-annotations. Это обеспечивает десятки из специфично для Android аннотаций, а также предоставляет общие как NonNull, Nullable и т.д.

Чтобы добавить пакет поддержки-аннотаций , добавьте следующую зависимость в ваш build.gradle:

compile 'com.Android.support:support-annotations:23.1.1'

а затем используйте:

import Android.support.annotation.NonNull;

void foobar(@NonNull Foo bar) {}
7
Shubham Chaudhary

Различают статический анализ и анализ времени выполнения. Используйте статический анализ для внутренних вещей и анализ времени выполнения для открытых границ вашего кода.

Для вещей, которые не должны быть нулевыми:

  • Проверка во время выполнения: используйте "if (x == null) ..." (нулевая зависимость) или @ javax.validation.NotNull (с проверкой бина) или @ lombok.NonNull (просто и просто) или guavas Preconditions.checkNotNull (.. .)

    • Используйте Необязательный для типов возвращаемых методов (только). Либо Java8, либо гуава.
  • Статическая проверка: используйте аннотацию @NonNull

  • Там, где это уместно, используйте аннотации @ ... NonnullByDefault на уровне класса или пакета. Создайте эти аннотации самостоятельно (примеры легко найти).
    • Иначе, используйте @ ... CheckForNull при возврате метода, чтобы избежать NPE

Это должно дать наилучший результат: предупреждения в среде IDE, ошибки от Findbugs и checkerframework, значимые исключения во время выполнения.

Не ожидайте, что статические проверки станут зрелыми, их имена не стандартизированы, а разные библиотеки и IDE обрабатывают их по-разному, игнорируют их. Классы JSR305 javax.annotations. * Выглядят как стандартные, но это не так, и они вызывают разделение пакетов с помощью Java9 +.

Некоторые примечания к объяснениям:

  • Аннотации Findbugs/spotbugs/jsr305 с пакетом javax.validation. * Конфликтуют с другими модулями в Java9 +, также могут нарушать лицензию Oracle
  • Аннотации Spotbugs по-прежнему зависят от аннотаций jsr305/findbugs во время компиляции (на момент написания https://github.com/spotbugs/spotbugs/issues/421 )
  • jetbrains @NotNull имя конфликтует с @ javax.validation.NotNull.
  • аннотации jetbrains, Eclipse или checkersframework для статической проверки имеют преимущество перед javax.annotations в том, что они не конфликтуют с другими модулями в Java9 и выше
  • @ javax.annotations.Nullable не означает для Findbugs/Spotbugs то, что вы (или ваша IDE) думаете, что это значит. Findbugs проигнорируют это (на участниках). Грустно, но верно ( https://sourceforge.net/p/findbugs/bugs/1181 )
  • Для статической проверки вне IDE существует 2 бесплатных инструмента: Spotbugs (ранее Findbugs) и checkersframework.
  • Библиотека Eclipse имеет @NonNullByDefault, jsr305 имеет только @ParametersAreNonnullByDefault. Это просто удобные обертки, применяющие базовые аннотации ко всему в пакете (или классе), вы можете легко создавать свои собственные. Это может быть использовано на упаковке. Это может конфликтовать с сгенерированным кодом (например, lombok).
  • Eclipse JDT аннотации не применяются к статическим методам возврата и некоторых других случаях
  • Следует избегать использования lombok в качестве экспортированной зависимости для библиотек, которыми вы делитесь с другими людьми: чем меньше транзитивных зависимостей, тем лучше
  • Использование инфраструктуры проверки Bean является мощным, но требует больших накладных расходов, так что это излишне, просто чтобы избежать ручной проверки нуля.
  • Использование Optional для полей и параметров метода является спорным (об этом вы можете легко найти статьи)
  • Пустые аннотации Android являются частью библиотеки поддержки Android, они поставляются с множеством других классов и не очень хорошо работают с другими аннотациями/инструментами

До Java9 это моя рекомендация:

// file: package-info.Java
@javax.annotation.ParametersAreNonnullByDefault
package example;


// file: PublicApi
package example;

public class PublicApi {

    /**
     * @param firstname MUST NOT be null
     * @param lastname MUST NOT be null
     */
    public Person createPerson(
            // Spotbugs ignores the param annotations, but IDEs will show problems
            @Nullable String firstname, // Users  might send null
            @Nullable String lastname // Users might send null
            ) {
        if (firstname == null) throw new IllagalArgumentException(...);
        if (lastname == null) throw new IllagalArgumentException(...);
        return doCreatePerson(fistname, lastname, nickname);
    }

    @NonNull // Spotbugs checks that method cannot return null
    private Person doCreatePerson(
             String firstname, // Spotbugs checks null cannot be passed, because package has ParametersAreNonnullByDefault
             String lastname,
             @Nullable String nickname // tell Spotbugs null is ok
             ) {
         return new Person(firstname, lastname, nickname);
    }

    @CheckForNull // Do not use @Nullable here, Spotbugs will ignore it, though IDEs respect it
    private Person getNickname(
         String firstname,
         String lastname) {
         return NICKNAMES.get(firstname + ':' + lastname);
    }
}

Обратите внимание, что нет способа заставить Spotbugs выдавать предупреждение при разыменовании параметра метода, допускающего значение NULL (на момент написания, версия 3.1 Spotbugs). Может быть, проверочная схема может сделать это.

6
tkruse

В ожидании того, что это будет рассмотрено в восходящем направлении (Java 8?), Вы также можете просто определить свои собственные локальные аннотации проекта @NotNull и @Nullable. Это может быть полезно также в том случае, если вы работаете с Java SE, где javax.validation.constraintsнедоступно по умолчанию.

import Java.lang.annotation.*;

/**
 * Designates that a field, return value, argument, or variable is
 * guaranteed to be non-null.
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@Documented
@Retention(RetentionPolicy.CLASS)
public @interface NotNull {}

/**
 * Designates that a field, return value, argument, or variable may be null.
 */
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
@Documented
@Retention(RetentionPolicy.CLASS)
public @interface Nullable {}

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

5
Arto Bendiken

Если вы работаете над большим проектом, вам может быть лучше создавать свои собственные @Nullable и/или @NotNull аннотации.

Например:

@Java.lang.annotation.Documented
@Java.lang.annotation.Retention(Java.lang.annotation.RetentionPolicy.CLASS)
@Java.lang.annotation.Target({Java.lang.annotation.ElementType.FIELD,
                              Java.lang.annotation.ElementType.METHOD,    
                              Java.lang.annotation.ElementType.PARAMETER,
                              Java.lang.annotation.ElementType.LOCAL_VARIABLE})
public @interface Nullable 
{
}

Если вы используете правильный политика хранения , тогда аннотации не будут доступны во время выполнения . С этой точки зрения, это просто внутренняя вещь.

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

  • Это внутренняя вещь. (без функционального или технического воздействия)
  • С много много много использования.
  • IDE, как IntelliJ, поддерживает пользовательские аннотации @Nullable/@NotNull.
  • Большинство фреймворков также предпочитают использовать свою собственную внутреннюю версию.

Дополнительные вопросы (см. Комментарии):

Как настроить это в IntelliJ?

Нажмите "Полицейский" в правом нижнем углу строки состояния IntelliJ. И нажмите "Настроить проверки" во всплывающем окне. Следующий ... configure annotations

4
bvdb

Если вы разрабатываете для Android, вы несколько привязаны к Eclipse (редактировать: на момент написания, больше нет), который имеет свои собственные аннотации , Он включен в Eclipse 3.8+ (Juno), но по умолчанию отключен.

Вы можете включить его в Предпочтения> Java> Компилятор> Ошибки/Предупреждения> Нулевой анализ (сворачиваемый раздел внизу).

Установите флажок "Включить нулевой анализ на основе аннотаций"

http://wiki.Eclipse.org/JDT_Core/Null_Analysis#Usage содержит рекомендации по настройке. Однако, если у вас есть внешние проекты в вашем рабочем пространстве (например, SDK facebook), они могут не соответствовать этим рекомендациям, и вы, вероятно, не хотите исправлять их при каждом обновлении SDK ;-)

Я использую:

  1. Доступ к нулевому указателю: ошибка
  2. Нарушение нулевой спецификации: ошибка (связана с пунктом 1)
  3. Потенциальный доступ к нулевому указателю: Предупреждение (в противном случае SDK facebook будет иметь предупреждения)
  4. Конфликт между нулевыми аннотациями и нулевым выводом: Предупреждение (связано с пунктом № 3)
4
chaqke

Есть еще один способ сделать это в Java 8. Я делаю 2 вещи, чтобы выполнить то, что мне нужно:

  1. Делая обнуляемые поля явными с типами, оборачивая обнуляемые поля с Java.util.Optional
  2. Проверка того, что все ненулевые поля не равны NULL во время построения с помощью Java.util.Objects.requireNonNull

Пример:

import static Java.util.Objects.requireNonNull;

public class Role {

  private final UUID guid;
  private final String domain;
  private final String name;
  private final Optional<String> description;

  public Role(UUID guid, String domain, String name, Optional<String> description) {
    this.guid = requireNonNull(guid);
    this.domain = requireNonNull(domain);
    this.name = requireNonNull(name);
    this.description = requireNonNull(description);
  }

Итак, мой вопрос: нужно ли даже комментировать при использовании Java 8?

Правка: Позже я узнал, что некоторые считают плохой практикой использовать Optional в аргументах, здесь есть хорошая дискуссия с плюсами и минусами Почему Java 8 Необязательно не использовать в аргументах знак равно

3
Mozart Brocchini

Если вы создаете свое приложение с использованием Spring Framework, я бы предложил использовать javax.validation.constraints.NotNull coming from Beans Validation , упакованный в следующую зависимость:

    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.1.0.Final</version>
    </dependency>

Основным преимуществом этой аннотации является то, что Spring обеспечивает поддержку как параметров метода, так и полей класса, аннотированных javax.validation.constraints.NotNull. Все, что вам нужно сделать, чтобы включить поддержку:

  1. предоставить jar api для проверки bean-компонентов и jar с реализацией валидатора аннотаций jsr-303/jsr-349 (который поставляется с зависимостью Hibernate Validator 5.x):

    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>1.1.0.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.4.1.Final</version>
    </dependency>
    
  2. предоставить MethodValidationPostProcessor для контекста Spring

      @Configuration
      @ValidationConfig
      public class ValidationConfig implements MyService {
    
            @Bean
            public MethodValidationPostProcessor providePostProcessor() {
                  return new MethodValidationPostProcessor()
            }
      }
    
  3. наконец, вы аннотируете свои классы с помощью Spring org.springframework.validation.annotation.Validated , и Spring будет автоматически обрабатывать проверку.

Пример:

@Service
@Validated
public class MyServiceImpl implements MyService {

  @Override
  public Something doSomething(@NotNull String myParameter) {
        // No need to do something like assert myParameter != null  
  }
}

Когда вы пытаетесь вызвать метод doSomething и передать значение null в качестве значения параметра, spring (с помощью HibernateValidator) сгенерирует ConstraintViolationException. Нет необходимости в ручной работе здесь.

Вы также можете проверить возвращаемые значения.

Другим важным преимуществом javax.validation.constraints.NotNull Coming для Beans Validation Framework является то, что на данный момент он все еще разрабатывается, и для новой версии 2.0 запланированы новые функции.

Как насчет @Nullable? Ничего подобного в Beans Validation 1.1 нет. Что ж, я мог бы поспорить, что если вы решите использовать @NotNull, то все, что НЕ аннотировано @NonNull, фактически "обнуляется", поэтому аннотация @Nullable бесполезна.

2
walkeros

Разве у Sun сейчас нет своего? Что это:
http://www.Java2s.com/Open-Source/Java-Document/6.0-JDK-Modules-com.Sun/istack/com.Sun.istack.internal.htm знак равно

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

Редактировать: Как уже упоминалось в комментариях ниже, вы, вероятно, не хотите использовать их. В этом случае мой голос за аннотации IntelliJ Jetbrains!

2
Nate W.

Другим вариантом являются аннотации, предоставляемые в ANTLR 4. После Запрос извлечения # 434 артефакт, содержащий аннотации @NotNull и @Nullable, включает в себя процессор аннотаций, который выдает ошибки времени компиляции и/или предупреждения в одном из следующих событий: эти атрибуты используются не по назначению (например, если оба применяются к одному и тому же элементу или если @Nullable применяется к элементу с примитивным типом). Процессор аннотаций обеспечивает дополнительную гарантию в процессе разработки программного обеспечения, что информация, передаваемая с помощью этих аннотаций, является точной, в том числе в случаях наследования методов.

1
Sam Harwell

Одна из замечательных особенностей IntelliJ заключается в том, что вам не нужно использовать их аннотации. Вы можете написать свой собственный или использовать любой другой инструмент, который вам нравится. Вы даже не ограничены одним типом. Если вы используете две библиотеки, которые используют разные аннотации @NotNull, вы можете указать IntelliJ использовать обе из них. Для этого перейдите в "Настроить проверки", нажмите "Постоянные условия и исключения" и нажмите кнопку "Настроить проверки". Я использую Nullness Checker везде, где могу, поэтому я настроил IntelliJ для использования этих аннотаций, но вы можете заставить его работать с любым другим инструментом, который вам нужен. (У меня нет мнения о других инструментах, потому что я использую проверки IntelliJ в течение многих лет, и я люблю их.)

1
MiguelMunoz

Здесь уже слишком много ответов, но (а) сейчас 2019 год, и до сих пор нет "стандартного" Nullable и (б) нет других ответов, ссылающихся на Kotlin.

Ссылка на Kotlin важна, потому что Kotlin на 100% совместим с Java и ​​имеет базовую функцию нулевой безопасности. При вызове библиотек Java эти аннотации могут использовать, чтобы инструменты Kotlin знали, может ли API Java принимать или возвращать null.

Насколько я знаю, единственными пакетами Nullable, совместимыми с Kotlin, являются org.jetbrains.annotations и Android.support.annotation (теперь androidx.annotation). Последний совместим только с Android, поэтому его нельзя использовать в проектах JVM/Java/Kotlin, отличных от Android. Тем не менее, пакет JetBrains работает везде.

Поэтому, если вы разрабатываете Java пакеты, которые также должны работать в Android и ​​Kotlin (и поддерживаться Android Studio и IntelliJ), ваш лучший выбор, вероятно, JetBrains пакет.

Maven:

<dependency>
    <groupId>org.jetbrains</groupId>
    <artifactId>annotations-Java5</artifactId>
    <version>15.0</version>
</dependency>

Gradle:

implementation 'org.jetbrains:annotations-Java5:15.0'
0
noamtm