2016-07-12 7 views
2

최근 Eclipse의 nullability 주석을 사용하여 Java 프로젝트를 업데이트하기 시작했습니다. 일부 번역 클래스가 포함 된 JavaFX 기본 프로젝트가 있습니다.형식 주석은 바운드 된 와일드 카드의 어디에 속합니까?

이제 내 LocalizedList에 문서 트리의 요소로 초기화하고 하위 요소를 모두 재귀 적으로 추가합니다. 난 그냥이와 함께 떠나는 경우

@NonNullByDefault 
private void locChildren(Styleable c) { 
    String localizable = getKey(c); 
    if(localizable != null) { 
     backingMap.put(c, localizable); 
     setText(c, localizable); 
    } 
    if(c instanceof MenuBar) { 
     MenuBar mb = (MenuBar)c; 
     initLoc(mb.getMenus()); 
    } // else if ... 
} 

@NonNullByDefault 
public void initLoc(List<? extends Styleable> s) { 
    for(Styleable c : s) { 
     locChildren(c); 
    } 
} 

지금, 나는 무섭게 긴 경고 메시지를받을

Null type safety (type annotations): The expression of type 'ObservableList<Menu>' needs unchecked conversion to conform to '@NonNull List<? extends @NonNull Styleable>', corresponding supertype is 'List<Menu>'

이것은 MenuBar#getMenus() 때문에 어떤 Null 허용 주석 주석되지 않고있다, 예상 될 수 있습니다.


@Nullable 주석을 List 자체에 적용한 후에도 문제가 해결되지 않았습니다. 그래서 @ Nullable을 와일드 카드에 추가했습니다. 이것은 내가 혼란스러워하는 것을 우연히 발견 한 곳입니다.

@NonNullByDefault 
public void initLoc1(@Nullable List<@Nullable ? extends Styleable> s) { 
    for(Styleable c : s) { 
     locChildren(c); 
    } 
} 

@NonNullByDefault 
public void initLoc2(@Nullable List<@Nullable ? extends @Nullable Styleable> s) { 
    for(Styleable c : s) { 
     locChildren(c); 
    } 
} 

@NonNullByDefault 
public void initLoc3(@Nullable List<? extends @Nullable Styleable> s) { 
    for(Styleable c : s) { 
     locChildren(c); 
    } 
} 

이 세 가지 선언은 모두 유효하고 잘 컴파일되지만 경고 메시지가 사라집니다.


나는 그것이 실제로 방법 자체에 사용되는, 완전히 두 번째 예를 혼동하고있는 "유형"을 주석으로 첫 번째는 유효 할 것으로 예상했을 것이다.

세 선언 사이의 의미상의 차이점은 무엇이며 왜 세 개는 작동하지만 두 개는 작동하지 않는 이유는 무엇입니까?

+2

컴파일러가 와일드 카드에서 형식 주석을 받아들이는 것에 약간 놀랐습니다. 유형이 아닙니다. 처음 두 경우에 나타나는 경고가 * *와 관련이 없다는 것을 확신합니까? 당신이 여전히 경고를 받는다는 사실에 초점을 맞추는 것이 어렵지 않을 수도 있으며, 그들이 다른 경고라는 사실을 간과 할 수도 있습니다. –

+0

@ 존 내가 제대로 이해했는지는 모르겠지만 세 가지 오류 메시지 (주석이없고 와일드 카드에 주석이 달린 주석이 달린 것)는 별개이지만 목록을 변경하면 <...> -type :'List ''@ NonNullByDefault' 주석과 같이,'List <@Nullable? 스타일 가능>'및'List <@Nullable? @ Nullable 스타일 가능>을 확장합니다. 나머지 경고는 그대로 유지됩니다. – Adowrath

+0

@ 존 아직 추론을 찾지 못했지만 자바 8 JLS에 추가 된 것으로 보인다. [JLS 8, 4.5.1] (https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.5.1) 및 [JLS 7, 4.5.1 ] (https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.5.1) – Adowrath

답변

1

원본 코드 예제를 이해하려면 정확히 @NonNullByDefault이라는 정확한 효과를 알아야합니다.이 효과는 enum DefaultLocation을 사용하여 미세 조정할 수 있습니다. 후자는

와일드 카드를 언급하며 형식 변수는 항상 NonNullByDefault에서 제외됩니다.

은 다른 한편으로 와일드 카드 extends Styleable @NonNullByDefault에 의해 영향을입니다 바인딩.

이는 예상되는 인수 유형이 initLoc 인 이유가 @NonNull List<? extends @NonNull Styleable> 인 이유를 설명합니다. 메서드 initLoc3은 여기에 표시된대로 두 개의 @NonNull 주석을 정확히 덮어 쓰므로 해당 위치에 명시적인 @Nullable을 명시함으로써 컴파일 오류를 해결합니다.

명시 적으로 @Nullable을 와일드 카드 자체에 적용하는 경우 Eclipse는 Checkers Framework 용으로 제안 된대로 concepts을 따릅니다. 특히 @Nullable ?은 Null 허용 속성이있는 상한 및 하한을 가진 것으로 해석됩니다.

initLoc2initLoc3에서 다른 이유가 설명 : 그것은 실제 인수로 다음 타의 추종을 불허 바인딩 추가 낮은을 정의합니다.

MenuBar에 관한 문제를 해결하려면 external annotations을 사용하는 것이 좋습니다.

면책 조항 : 표시된 방법의 클래스 컨텍스트가 부족했기 때문에 상황을 정확히 재현 할 수 없었습니다. getKey, backingMapsetText의 출처는 어디입니까?

+0

'setText'와'getKey'는 서명'void setText (Styleable, String)'과'@Nullable String getKey (Styleable)'을 가진 로컬 메소드입니다. 빈 몸체/기본 반환 값을 그대로 둘 수 있습니다. 'backingMap'은 간단한'Map '입니다. 나는'DefaultLocation' 열거 형을 읽었고 initLoc 메쏘드에 대해'TYPE_BOUND'를 제거하고 변환을'@ NonNull'으로 유지하기위한 어설 션을 추가했습니다. 나는'initLoc2'가 정확히 어떻게 다른지 이해하지 못합니다. - extends 절에 의해'@ Nullable' 상한이 있다면, 두 번째'@ Nullable'을 추가하면 정확히 무엇이 나옵니 까? – Adowrath

+0

아, 제 생각에'Menu'는'@Nullable Menu'의 수퍼 타입이 아닙니다. 당신의 추가를 당신을 감사하십시오, 나는 응답을 받아 들였다. – Adowrath