IT박스

@Nullable 및 @Nonnull 주석을보다 효과적으로 사용하는 방법은 무엇입니까?

itboxs 2020. 7. 20. 07:51
반응형

@Nullable 및 @Nonnull 주석을보다 효과적으로 사용하는 방법은 무엇입니까?


나는 그것을 볼 수 있습니다 @Nullable@Nonnull주석 예방에 도움이 될 NullPointerException들하지만 그들은 아주 멀리 전파되지 않습니다.

  • 이러한 주석의 효과는 한 수준의 간접적 인 후에 완전히 사라 지므로 몇 가지만 추가하면 아주 많이 전파되지 않습니다.
  • 이러한 주석이 제대로 적용되지 않기 때문에로 표시된 값 @Nonnull이 널이 아니라고 가정 하여 널 검사를 수행하지 않을 위험이 있습니다.

아래 코드는 불만을 제기하지 않은 것으로 표시된 매개 변수가 발생 @Nonnull하도록합니다 null. NullPointerException실행 되면를 던집니다 .

public class Clazz {
    public static void main(String[] args){
        Clazz clazz = new Clazz();

        // this line raises a complaint with the IDE (IntelliJ 11)
        clazz.directPathToA(null);

        // this line does not
        clazz.indirectPathToA(null); 
    }

    public void indirectPathToA(Integer y){
        directPathToA(y);
    }

    public void directPathToA(@Nonnull Integer x){
        x.toString(); // do stuff to x        
    }
}

이러한 주석을보다 엄격하게 적용 및 / 또는 더 전파 할 수있는 방법이 있습니까?


짧은 대답 :이 주석은 IDE에서 잠재적으로 null 포인터 오류를 경고하는 데 유용합니다.

"Clean Code"책에서 말했듯이 공용 메소드의 매개 변수를 확인하고 불변 값을 확인하지 않아야합니다.

또 다른 좋은 팁은 null 값을 반환하지 않지만 대신 Null Object Pattern을 사용하는 것입니다.


IDE null가 null이 아닌 곳으로 전달한다는 힌트를주는 IDE 외에도 다음과 같은 장점이 있습니다.

  • 정적 코드 분석 도구는 IDE와 동일한 테스트를 수행 할 수 있습니다 (예 : FindBugs)
  • AOP를 사용하여이 어설 션을 확인할 수 있습니다

따라서 유지 관리가 용이하고 (확인할 필요가없고 null) 오류가 적은 코드를 작성하는 데 도움이됩니다 .


준수 1.8에서 Eclipse의 원래 예제를 컴파일하고 주석 기반 널 분석을 사용하면 다음 경고가 표시됩니다.

    directPathToA(y);
                  ^
Null type safety (type annotations): The expression of type 'Integer' needs unchecked conversion to conform to '@NonNull Integer'

이 경고는 원시 유형을 사용하여 생성 된 코드와 레거시 코드를 혼합 할 때 발생하는 경고 ( "확인되지 않은 변환")와 유사합니다. 여기에는 똑같은 상황이 있습니다. method indirectPathToA()에는 null 계약을 지정하지 않는다는 점에서 "legacy"서명이 있습니다. 툴은이를 쉽게보고 할 수 있으므로 널 어노테이션이 전파되어야하지만 아직 그렇지 않은 모든 골목을 추적합니다.

그리고 영리한 @NonNullByDefault것을 사용할 때 마다 우리는 매번 이것을 말할 필요조차 없습니다.

다시 말해, 널 어노테이션이 "매우 멀리 전파"되는지 여부는 사용하는 도구 및 도구가 발행 한 모든 경고에 얼마나 엄격하게 참여하는지에 따라 달라질 수 있습니다. TYPE_USE 널 어노테이션사용하면 널 (null) 이 유형 시스템의 중요한 특성이 되었기 때문에 도구가 프로그램에서 가능한 모든 NPE에 대해 경고 할 수있는 옵션이 있습니다.


이 원래의 질문은 @NonNull을 사용하더라도 런타임 null 포인터 검사가 여전히 필요하다는 일반적인 권장 사항을 간접적으로 가리키는 것으로 생각합니다. 다음 링크를 참조하십시오.

Java 8의 새로운 타입 주석

위의 블로그에서 다음을 권장합니다.

선택적 유형 주석은 런타임 유효성 검증을 대체하지 않습니다. 유형 주석 이전에 널 (null) 가능성 또는 범위와 같은 항목을 설명하는 기본 위치는 javadoc에있었습니다. 형식 주석을 사용하면이 통신은 컴파일 타임 확인을 위해 바이트 코드로 들어옵니다. 코드는 여전히 런타임 유효성 검사를 수행해야합니다.


나는 주석이 "아주 멀리 전파되지 않음"에 동의합니다. 그러나 나는 프로그래머 측에서 실수를 본다.

Nonnull주석을 문서로 이해합니다 . 다음 메소드는 널이 아닌 인수가 필요한 (전제 조건으로) 표현합니다 x.

    public void directPathToA(@Nonnull Integer x){
        x.toString(); // do stuff to x        
    }

The following code snippet then contains a bug. The method calls directPathToA() without enforcing that y is non-null (that is, it does not guarantee the precondition of the called method). One possibility is to add a Nonnull annotation as well to indirectPathToA() (propagating the precondition). Possibility two is to check for the nullity of y in indirectPathToA() and avoid the call to directPathToA() when y is null.

    public void indirectPathToA(Integer y){
        directPathToA(y);
    }

What I do in my projects is to activate the following option in the "Constant conditions & exceptions" code inspection:
Suggest @Nullable annotation for methods that may possibly return null and report nullable values passed to non-annotated parameters 검사

When activated, all non-annotated parameters will be treated as non-null and thus you will also see a warning on your indirect call:

clazz.indirectPathToA(null); 

For even stronger checks the Checker Framework may be a good choice (see this nice tutorial.
Note: I have not used that yet and there may be problems with the Jack compiler: see this bugreport


In Java I'd use Guava's Optional type. Being an actual type you get compiler guarantees about its use. It's easy to bypass it and obtain a NullPointerException, but at least the signature of the method clearly communicates what it expects as an argument or what it might return.


If you use Kotlin, it supports these nullability annotations in its compiler and will prevent you from passing a null to a java method that requires a non-null argument. Event though this question was originally targeted at Java, I mention this Kotlin feature because it is specifically targeted at these Java annotation and the question was "Is there a way to make these annotations more strictly enforced and/or propagate further?" and this feature does make these annotation more strictly enforced.

Java class using @NotNull annotation

public class MyJavaClazz {
    public void foo(@NotNull String myString) {
        // will result in an NPE if myString is null
        myString.hashCode();
    }
}

Kotlin class calling Java class and passing null for the argument annotated with @NotNull

class MyKotlinClazz {
    fun foo() {
        MyJavaClazz().foo(null)
    }
}  

Kotlin compiler error enforcing the @NotNull annotation.

Error:(5, 27) Kotlin: Null can not be a value of a non-null type String

참조 : http://kotlinlang.org/docs/reference/java-interop.html#nullability-annotations

참고 URL : https://stackoverflow.com/questions/13484202/how-to-use-nullable-and-nonnull-annotations-more- 효과적으로

반응형