이후 JSR 305 (누구의 목표를 표준화하는 것이었다 @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
별도로 나열합니다. 롬복은 꽤 지루 @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
...에서 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