[java] @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을 사용하는 것입니다.


답변

null인수가 널이 아닌 것으로 예상되는 메소드에 전달할 때 힌트를 제공하는 IDE 이외의 다른 장점이 있습니다.

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

이렇게하면 코드를 유지 관리 null하기 쉽고 (확인할 필요가 없기 때문에 ) 오류 발생 가능성이 줄어 듭니다.


답변

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

Java 8의 새로운 타입 주석

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

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


답변

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

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

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

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

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


답변

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

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

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

다음 코드 스 니펫에는 버그가 포함되어 있습니다. 메소드는 널이 아닌 directPathToA()것을 강제하지 않고 호출합니다 y(즉, 호출 된 메소드의 전제 조건을 보장하지는 않습니다). 한 가지 가능성은 Nonnull주석 을 추가하는 것 indirectPathToA()(전제 조건 전파)입니다. 가능성 2는 yin의 null을 확인하고 null indirectPathToA()directPathToA()되었을 때 의 호출을 피하는 것 y입니다.

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


답변

프로젝트에서 수행하는 작업은 “일정한 조건 및 예외”코드 검사에서 다음 옵션을 활성화하는 것입니다. null을 반환하고 주석이없는 매개 변수에 전달 된 nullable 값을보고 할 수있는 메서드에 @Nullable 주석을 제안하십시오 .

검사

활성화되면 주석이없는 모든 매개 변수가 널이 아닌 것으로 취급되므로 간접 호출에 대한 경고도 표시됩니다.

clazz.indirectPathToA(null); 

더 강력한 검사를 위해 Checker Framework가 좋은 선택 일 수 있습니다 (이 훌륭한 자습서를 참조하십시오 .
참고 : 아직 사용하지 않았으며 Jack 컴파일러에 문제가있을 수 있습니다 : 이 버그 보고서를 참조하십시오


답변

Java에서는 Guava의 Optional type을 사용 합니다 . 실제 유형이기 때문에 컴파일러는 그 사용에 대해 보장합니다. 그것을 우회하고 쉽게 얻을 수 NullPointerException있지만 적어도 메소드의 서명은 인수로 기대하는 것 또는 반환 할 수있는 것을 명확하게 전달합니다.