질문 : 어떤 @NotNull Java 주석을 사용해야합니까?
NullPointerExceptions를 방지하기 위해 IDE 코드 검사 및 / 또는 정적 코드 분석 (FindBugs 및 Sonar)과 같은 도구를 사용하는 것뿐만 아니라 코드를 더 읽기 쉽게 만들고 싶습니다. 많은 도구가 서로의 @NotNull
/ @NonNull
/ @Nonnull
주석과 호환되지 않는 것처럼 보이며 모두 내 코드에 나열하면 읽기가 끔찍합니다. 어떤 것이 '최고'인지에 대한 제안이 있습니까? 내가 찾은 동등한 주석 목록은 다음과 같습니다.
javax.validation.constraints.NotNull
정적 분석이 아닌 런타임 유효성 검사를 위해 생성되었습니다.
선적 서류 비치edu.umd.cs.findbugs.annotations.NonNull
FindBugs ( 죽은 프로젝트 )와 그 후속 SpotBugs 정적 분석 및 Sonar (현재 Sonarqube )에서 사용
FindBugs 문서 , SpotBugs 문서javax.annotation.Nonnull
FindBugs에서도 작동 할 수 있지만 JSR-305 는 비활성 상태입니다. (참조 : JSR 305의 상태는 무엇입니까? ) 소스org.jetbrains.annotations.NotNull
정적 분석을 위해 IntelliJ IDEA IDE에서 사용됩니다.
선적 서류 비치lombok.NonNull
Project Lombok 에서 코드 생성을 제어하는 데 사용됩니다.
표준이 없으므로 자리 표시 자 주석입니다.
소스 , 문서android.support.annotation.NonNull
Android에서 사용 가능한 마커 주석 (support-annotations 패키지에서 제공)
선적 서류 비치org.eclipse.jdt.annotation.NonNull
정적 코드 분석을 위해 Eclipse에서 사용
선적 서류 비치
답변
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와 함께 제공됩니다. 이것이 결국 JSE와 함께 제공되거나 전혀 제공되지 않는 javax.annotation
보다 낫다면 논쟁의 여지가 있습니다. JEE 종속성이 마음에 들지 않기 때문에 개인적으로 javax.annotation
이것은 우리에게
javax.annotation
이것은 또한 가장 짧은 것입니다.
더 나은 구문은 java.annotation.Nullable
입니다. 과거에 다른 패키지가 javax
에서 java
로 전환되었으므로 javax.annotation은 올바른 방향으로 나아가는 단계가 될 것입니다.
구현
나는 그들이 모두 기본적으로 똑같은 사소한 구현을 갖기를 바랐지만 자세한 분석은 이것이 사실이 아니라는 것을 보여주었습니다.
먼저 유사점 :
@NonNull
주석에는 모두 다음 줄이 있습니다.
public @interface NonNull {}
제외하고
@NotNull
이라고 부르고 간단한 구현이있는org.jetbrains.annotations
- 더 긴 구현이있는
javax.annotation
@NotNull
이라고도 부르고 구현이있는javax.validation.constraints
@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 스타일 컨텍스트를 사용합니다. 다음 표는 개요를 제공합니다.
FIELD METHOD PARAMETER LOCAL_VARIABLE
android.support.annotation X X X
edu.umd.cs.findbugs.annotations X X X X
org.jetbrains.annotation X X X X
lombok X X X X
javax.validation.constraints X X X
org.eclipse.jdt.annotation
, javax.annotation
및 org.checkerframework.checker.nullness.qual
은 JLS 4.11에 정의 된 컨텍스트를 사용하는데, 이는 제 생각에는 올바른 방법입니다.
이것은 우리에게
javax.annotation
org.checkerframework.checker.nullness.qual
이번 라운드에서.
코드
자세한 내용을 직접 비교할 수 있도록 아래에 모든 주석의 코드를 나열합니다. 비교를 더 쉽게하기 위해 주석, 가져 오기 및 @Documented
주석을 제거했습니다. (Android 패키지의 클래스를 제외하고 @Documented
줄과 @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에서 즉시 지원됩니다.
요약
이상적인 주석은 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
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
gwt-dev-2.5.1-sources.jar
javax.annotation
org.checkerframework.checker.nullness.qual
의checker-framework-2.1.9.zip
lombok
commitf6da35e4c4f3305ecd1b415e2ab1b9ef8a9120b4
에서lombok
validation-api-1.0.0.GA-sources.jar
javax.validation.constraints
출처 : https://stackoverflow.com/questions/4963300/which-notnull-java-annotation-should-i-use
'프로그래밍 언어 > JAVA' 카테고리의 다른 글
Java "."(점)으로 분할 된 문자열을 만드는 방법 (0) | 2021.12.29 |
---|---|
Java에서 파일의 파일 확장자를 얻는 방법 (0) | 2021.12.29 |
java.lang.NoClassDefFoundError 해결 방법 : javax / xml / bind / JAXBException (0) | 2021.12.29 |
Java에서 파일을 byte []로 변환하는 방법 (0) | 2021.12.29 |
JAVA Implements vs extends 차이점과 사용시기 (0) | 2021.12.29 |