以来JSR 305(その目標は標準化した@NonNull
とは@Nullable
)数年前から休眠てきた、私は良い答えがない怖いです。私たちにできることは、実用的な解決策を見つけることだけです。私のものは次のとおりです。
構文
純粋な文体の観点から、Java以外のIDE、フレームワーク、またはツールキットへの参照は避けたいと思います。
これは除外します:
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 {}
を除いて
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の回答でいる、ランタイムアノテーションの影響は考えられるよりも小さいですが、コンパイル時のアノテーションに加えてランタイムチェックを行うツールを有効にするという利点があります。
もう1つの重要な違いは、、コードので注釈を使用できるかです。2つの異なるアプローチがあります。一部のパッケージは、JLS 9.6.4.1スタイルのコンテキストを使用します。次の表に概要を示します。
FIELD METHOD PARAMETER 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 {}
次の2つのパッケージにはがないため@Nullable
、個別にリストします。ロンボクはかなり退屈@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とチェッカーフレームワークはそのまま使用できます。
概要
私の理想的な注釈は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
から findbugs-annotations-1.0.0.jar
org.eclipse.jdt.annotation
から org.eclipse.jdt.annotation_2.1.0.v20160418-1457.jar
org.jetbrains.annotations
から 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
コミットからf6da35e4c4f3305ecd1b415e2ab1b9ef8a9120b4
javax.validation.constraints
から validation-api-1.0.0.GA-sources.jar