web-dev-qa-db-ja.com

どの@NotNull Javaアノテーションを使用すればよいですか?

NullPointerExceptionsを回避するために、コードを読みやすくし、IDEコード検査や静的コード分析(FindBugsおよびSonar)などのツールを使用することを検討しています。これらのツールの多くはお互いの@NotNull/@NonNull/@Nonnullアノテーションと互換性がないように見え、それらすべてを私のコードにリストするのは読むのがひどいでしょう。どれが「ベスト」であるという提案はありますか?これが私が見つけた同等のアノテーションのリストです:

856
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

これも最短です。

さらに優れた構文が1つだけあります。Java.annotation.Nullable。過去に他のパッケージがjavaxからJavaに変わったので、javax.annotationは正しい方向への一歩になるでしょう。

実装

私は彼ら全員が基本的に同じ些細な実装を持っていることを望んでいましたが、詳細な分析はこれが本当ではないことを示しました。

まず類似点について

@NonNullアノテーションはすべて次の行を持っています

public @interface NonNull {}

を除いて

  • @NotNullと呼ばれ、簡単な実装を持つorg.jetbrains.annotations
  • より長い実装を持つ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))。

this SO answer で説明されているように、ランタイムアノテーションの影響は想像以上に小さいですが、それらはコンパイル時のものに加えてツールがランタイムチェックをすることを可能にするという利点があります。

もう1つの重要な違いは、アノテーションを使用できるコード内のwhereです。 2つの異なるアプローチがあります。一部のパッケージは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アノテーションを削除しました。 (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 {}

完全を期すために、@ null許容の実装は次のとおりです。

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 {}

次の2つのパッケージには@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によってサポートされています。

概要

私の理想的なアノテーションは、Checker Frameworkを実装したJava.annotationの構文です。

Checker Frameworkを使用しないのであれば、 javax.annotation JSR-305 )がまだ当面の間あなたの最善の策です。

Checker Frameworkを購入したい場合は、単に彼らのorg.checkerframework.checker.nullness.qualを使用してください。


出典

  • Android-5.1.1_r1.jarからのAndroid.support.annotation
  • findbugs-annotations-1.0.0.jarからのedu.umd.cs.findbugs.annotations
  • org.Eclipse.jdt.annotation_2.1.0.v20160418-1457.jarからのorg.Eclipse.jdt.annotation
  • jetbrains-annotations-13.0.jarからのorg.jetbrains.annotations
  • gwt-dev-2.5.1-sources.jarからのjavax.annotation
  • checker-framework-2.1.9.Zipからのorg.checkerframework.checker.nullness.qual
  • ロンボクコミットからロンボクf6da35e4c4f3305ecd1b415e2ab1b9ef8a9120b4
  • validation-api-1.0.0.GA-sources.jarからのjavax.validation.constraints
118

私は Checker Framework がとても好きです。これはnullness checkerのような欠陥チェッカーを実装するのに使われる型注釈の実装です( JSR-308 )。私は他のどの人も比較を提供しようとはしていませんが、私はこの実装に満足しています。

私はソフトウェアを提供するグループと提携していませんが、私はファンです。

このシステムについて私が好きな4つのこと:

  1. それは nullness (@Nullable)のための欠陥チェッカーを持っていますが、 immutability そして interning (そしてその他のもの)のためのものも持っています。最初のもの(nullness)を使い、2番目のもの(immutability/IGJ)を使い始めるようにしています。私は3番目のものを試しています、しかし私はまだそれを長期間使用することについて確信がありません。私はまだ他のチェッカーの一般的な有用性を確信していませんが、フレームワーク自体がさまざまな追加のアノテーションとチェッカーを実装するためのシステムであることを知っているのはいいことです。

  2. Nullnessのチェックのための デフォルト設定 はうまく機能します。ローカル以外のnull以外(NNEL)。基本的にこれは、デフォルトではチェッカーがローカル変数を除くすべてのアッシング(インスタンス変数、メソッドパラメータ、ジェネリック型など)をデフォルトで@NonNull型を持つものとして扱うことを意味します。ドキュメントごとに:

    NNELのデフォルトでは、コード内で明示的な注釈が最も少なくなります。

    NNELが機能しない場合は、クラスまたはメソッドに異なるデフォルトを設定できます。

  3. このフレームワークでは、注釈をコメントで囲むことでフレームワークへの依存関係を作成することなくを使用できます。 /*@Nullable*/。ライブラリや共有コードに注釈を付けてチェックすることはできますが、それでもフレームワークを使用しない別のプロジェクトでそのライブラリ/共有コードを使用することができるので、これは素晴らしいことです。これはいい機能です。私は今私のすべてのプロジェクトでChecker Frameworkを有効にする傾向がありますが、私はそれを使うことに慣れてきました。

  4. このフレームワークには、 APIに注釈を付ける方法があります。 スタブファイルを使用してnullの注釈がまだ付けられていないAPIを使用することができます。

84
Bert F

私はIntelliJを使用しています。なぜなら、私はIntelliJがNPEを生み出す可能性のあるものにフラグを立てることを主に心配しているからです。 JDKに標準の注釈がないことにイライラすることに同意します。それを追加することについての話があります、それはそれをJava 7にするかもしれません。その場合その中から選ぶべきもう1つがあるでしょう!

51
Sam Barnum

Java 7の機能リストによると JSR-308型の注釈はJava 8に延期されています。JSR-305注釈は言及されていません。

最新のJSR-308ドラフトの 付録 には、JSR-305の状態に関する情報が少しあります。これにはJSR-305アノテーションが放棄されているように見えるという観察も含まれます。 JSR-305ページでも「非アクティブ」と表示されています。

その一方で、実用的な答えは、最も広く使用されているツールでサポートされている注釈型を使用することです。


実際、JSR-308はアノテーションタイプ/クラスを定義していません、そしてそれは彼らがそれが範囲外であると思うように見えます。 (そしてJSR-305の存在を考えると、それらは正しいです)。

しかし、JSR-308が本当にJava 8になったように見えるのであれば、JSR-305への興味が復活しても私は驚かないでしょう。私の知る限り、JSR-305チームは正式に彼らの仕事を放棄していません。彼らは2年以上静かになっています。

Bill Pugh(JSR-305の技術リーダー)がFindBugsの背後にいる人の1人であることは興味深いです。

32
Stephen C

Androidプロジェクトの場合は、Android.support.annotation.NonNullAndroid.support.annotation.Nullableを使用する必要があります。これらおよびその他の便利なAndroid固有のアノテーションは Support Library にあります。

http://tools.Android.com/tech-docs/support-annotations から:

サポートライブラリ自体もこれらのアノテーションでアノテーションが付けられているので、サポートライブラリのユーザとして、Android Studioはすでにあなたのコードをチェックし、これらのアノテーションに基づいて潜在的な問題にフラグを立てます。

25
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 _ :2012年12月12日現在 JSR 305 は「休止中」と表示されています。ドキュメントによると:

執行委員会によって「休止中」として投票されたJSR、またはその自然な寿命の終わりに達したもの。

JSR 308 is はJDK 8になります。JSRでは@NotNullは定義されていませんが、付随するCheckers Frameworkは定義されています。これを書いている時点では、Mavenプラグインはこのバグのため使用できません: https://github.com/typetools/checker-framework/issues/183

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

Java Validation API(javax.validation.constraints.*)には@Nullableアノテーションが付いていないことを指摘してください。これは静的分析のコンテキストでは非常に有益です。これはランタイムBeanの検証には意味があります。これはJavaの非プリミティブフィールドのデフォルトです(つまり、検証/強制するものは何もない)からです。目的のためにそれは選択肢に向かって重視すべきであると述べた。

11
Ophir Radnitz

残念ながら、JSR 308はこのプロジェクトのローカル値以上の値を追加することはありません。

Java 8には単一のデフォルトアノテーションやそれ自身のCheckerフレームワークは付属しません。 Find-bugsやJSR 305と同じように、このJSRはほとんどが学術的なチームで構成されているわけではありません。

その背後には商業的権力がないため、JSR 308EDR 3JCPでの早期ドラフトレビュー)を今すぐ開始します。一方、Java 8は6か月以内に出荷される予定です。しかし、310が創設者から離れていることとは異なり、308 OracleはJavaプラットフォームへの害を最小限に抑えるためにこれを担当しました。

Checker FrameworkおよびJSR 308の背後にあるもののようなすべてのプロジェクト、ベンダー、および学術クラスは、独自の独自のチェッカーアノテーションを作成します。

いくつかの一般的な妥協点が見つかってJava 910に追加されるまで、あるいはApache CommonsGoogle Guava ;-)のようなフレームワークを介して追加されるまで、ソースコードを今後何年もの間非互換にする

7
Werner Keil

アンドロイド

この答えはAndroidに固有のものです。 Androidはsupport-annotationsと呼ばれるサポートパッケージを持っています。これは 数十 / Android固有 のアノテーションを提供し、また 共通のものNonNullNullableなどを提供します.

support-annotations packageを追加するには、build.gradleに次の依存関係を追加します。

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

それから:

import Android.support.annotation.NonNull;

void foobar(@NonNull Foo bar) {}
7

静的分析と実行時分析を区別します。内部のものには静的解析を使用し、コードの公開境界には実行時解析を使用します。

Nullであってはいけないことのために:

  • 実行時検査: "if(x == null)..."(依存性ゼロ)、または@ javax.validation.NotNull(Bean検証あり)、または@ lombok.NonNull(プレーンでシンプル)またはguavas Preconditions.checkNotNull(..) 。)

    • メソッドの戻り型にはOptionalを使用します(のみ)。 Java 8かGuavaのどちらかです。
  • 静的チェック:@NonNullアノテーションを使う

  • 収まる場所では、クラスレベルまたはパッケージレベルで@ ... NonnullByDefault注釈を使用します。これらの注釈を自分で作成してください(例は見つけやすいです)。
    • そうでない場合は、NPEを回避するためにメソッドの戻り値に@ ... CheckForNullを使用します。

IDEでの警告、Findbugsによるエラー、checkerframework、意味のある実行時例外など、これが最良の結果をもたらします。

静的チェックが成熟することを期待しないでください、それらの命名は標準化されていません、そして、異なるライブラリーとIDEはそれらを違うように扱います、それらを無視してください。 JSR305のjavax.annotations。*クラスは標準のように見えますが、そうではなく、Java9 +で分割パッケージを引き起こします。

いくつかの注釈の説明:

  • パッケージjavax.validation。*のFindbugs/spotbugs/jsr305アノテーションがJava9 +の他のモジュールと衝突し、これもOracleのライセンスに違反している可能性があります
  • Spotbugsアノテーションはコンパイル時にはまだjsr305/findbugsアノテーションに依存しています(執筆時点では https://github.com/spotbugs/spotbugs/issues/421
  • jetbrains @NotNull名は@ javax.validation.NotNullと競合します。
  • 静的チェックのためのjetbrains、Eclipseまたはcheckersframeworkアノテーションは、それらがJava9以降の他のモジュールと衝突しないというjavax.annotationsよりも優れています。
  • @ 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検証フレームワークの使用は強力ですが、高いオーバーヘッドを必要とするため、手動によるnullチェックを避けるためにはやり過ぎです。
  • フィールドとメソッドパラメータにOptionalを使用することは物議を醸しています(あなたはそれについての記事を簡単に見つけることができます)
  • Androidのnullアノテーションは、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);
    }
}

Nullを許容するメソッドパラメータが間接参照されたときにSpotbugsに警告を発生させる方法はないことに注意してください(執筆時点では、Spotbugsのバージョン3.1)。多分checkerframeworkはそれをすることができます。

6
tkruse

これが上流でソートされるのを待っている間(Java 8?)、独自のプロジェクトローカルの@NotNullおよび@Nullableアノテーションを定義することもできます。これは、デフォルトでjavax.validation.constraintsが利用できない であるJava SEで作業している場合にも役に立ちます。

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 
{
}

正しい 保存方針 を使用すると、アノテーション は実行時に使用できなくなります 。その観点からすると、それは単なる internal です。

これは厳密な科学ではありませんが、 internal クラスを使うのが最も理にかなっていると思います。

  • それは内部のものです。 (機能的または技術的影響なし)
  • たくさんのたくさんの用途で。
  • IntelliJのようなIDEはカスタムの@Nullable/@NotNullアノテーションをサポートします。
  • ほとんどのフレームワークはそれ自身の内部バージョンを使うことを好みます。

追加の質問(コメント参照):

IntelliJでこれを設定するにはどうすればいいですか?

IntelliJステータスバーの右下隅にある「警察官」をクリックしてください。そしてポップアップの "検査の設定"をクリックしてください。次 ...  configure annotations

4
bvdb

Android用に開発しているのであれば、 やや はEclipseに結び付けられています(編集:執筆時点ではなくなりました)。独自のアノテーションがあります。 Eclipse 3.8以降(Juno)には含まれていますが、デフォルトでは無効になっています。

それは、Preferences> Java> Compiler> Errors/Warnings> Null analysis(一番下の折りたたみ可能なセクション)で有効にできます。

「アノテーションベースのnull分析を有効にする」にチェックを入れます

http://wiki.Eclipse.org/JDT_Core/Null_Analysis#Usage に設定に関する推奨事項があります。ただし、ワークスペースに外部プロジェクトがある場合(facebook SDKなど)、これらの推奨事項を満たしていない可能性があります。おそらく、SDKを更新するたびにそれらを修正したくないでしょう;-)

私が使う:

  1. NULLポインタアクセス:エラー
  2. Null指定違反:エラー(ポイント#1へのリンク)
  3. 潜在的なnullポインタアクセス:警告(そうでなければfacebook SDKは警告を持っているでしょう)
  4. Null注釈とnull推論の衝突:警告(ポイント#3にリンク)
4
chaqke

Java 8でこれを行うには別の方法があります。私は必要なことを達成するために2つのことをしています。

  1. Null許容フィールドをJava.util.Optionalでラップすることで、null許容フィールドを型で明示的にする
  2. Java.util.Objects.requireNonNullを使用して、作成時にNULL入力不可フィールドがすべてNULLではないことを確認する

例:

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のOptionalは議論で使用されるべきでない

3

もしあなたがSpring Frameworkを使ってあなたのアプリケーションを構築しているなら、私は Beans Validation から来るjavax.validation.constraints.NotNullを使うことをお勧めします。

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

このアノテーションの主な利点は、Springがjavax.validation.constraints.NotNullでアノテーションされたメソッドパラメータとクラスフィールドの両方のサポートを提供することです。サポートを有効にするために必要なのは、次のとおりです。

  1. beanの検証用のAPI jarとjsr-303/jsr-349アノテーションの検証用の実装を含むjar(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. springのコンテキストにMethodValidationPostProcessorを提供する

      @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をスローします。ここでは手作業は必要ありません。

戻り値を検証することもできます。

Beans Validation Frameworkに来るjavax.validation.constraints.NotNullのもう1つの重要な利点は、現時点ではまだ開発中であり、新しいバージョン2.0に対して新しい機能が計画されていることです。

@Nullableはどうですか? Beans Validation 1.1にはそんなことはありません。 @NotNullでアノテートされていないすべてのものより@NonNullを使用することを決定した場合、@Nullableアノテーションは役に立たないと考えることができます。

2
walkeros

太陽は今自分のものを持っていませんか?これは何ですか:
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.

プルリクエスト#434 に続いて、@NotNullおよび@Nullableアノテーションを含むアーティファクトには、これらの属性の1つが発生した場合にコンパイル時エラーや警告を生成するアノテーションプロセッサが含まれます。誤用されている(例えば、両方が同じ項目に適用されている場合、または@Nullableがプリミティブ型の項目に適用されている場合)。アノテーションプロセッサは、ソフトウェア開発プロセス中に、メソッド継承の場合を含め、これらのアノテーションの適用によって伝達される情報が正確であるという追加の保証を提供します。

1
Sam Harwell

IntelliJの優れた点の1つは、注釈を使用する必要がないということです。あなたはあなた自身のものを書くことができますか、あなたはあなたが好きな他のどんなツールのものでも使うことができます。あなたはシングルタイプにさえ制限されていません。異なる@NotNullアノテーションを使用する2つのライブラリを使用している場合は、両方を使用するようにIntelliJに指示することができます。これを行うには、[検査の設定]に移動し、[定数と例外]検査をクリックして、[検査の設定]ボタンをクリックします。私はできる限りNullness Checkerを使っているので、それらのアノテーションを使うようにIntelliJを設定しましたが、他のどんなツールでも動作させることができます。 (私は何年もIntelliJの検査を使用してきたので、他のツールについては意見がありません。そしてそれらが大好きです。)

1
MiguelMunoz

ここにはすでにあまりにも多くの答えがありますが、(a)2019年です。まだ(標準の)Nullableはありません。

KotlinはJavaと100%相互運用可能であり、Null Safetyのコア機能を備えているため、Kotlinへの参照は重要です。 Javaライブラリを呼び出すとき、それらのアノテーションを利用して、KotlinツールにJava APIがnullを受け入れることができるかどうかを知らせることができます。

私の知る限りでは、Kotlinと互換性のあるNullableパッケージはorg.jetbrains.annotationsAndroid.support.annotation(現在はandroidx.annotation)です。後者はAndroidとのみ互換性があるため、Android以外のJVM/Java/Kotlinプロジェクトでは使用できません。しかし、JetBrainsパッケージはどこでも動作します。

したがって、AndroidとKotlinでも動作する(そしてAndroid StudioとIntelliJでサポートされる)Javaパッケージを開発するなら、おそらくJetBrainsパッケージが最善の選択です。

メイヴン:

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

Gradle:

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