2016-11-22 115 views
0

如何擺脫本示例代碼中的警告。如何擺脫TreeMap中eclipse neon中的「空類型安全」警告

我使用Eclipse霓虹燈與Java 1.8和org.eclipse.jdt.annotation_2.1.0

import java.util.Iterator; 
import java.util.Map.Entry; 
import java.util.Set; 
import java.util.TreeMap; 

import org.eclipse.jdt.annotation.NonNullByDefault; 
import org.eclipse.jdt.annotation.Nullable; 

@NonNullByDefault 
public class NullAnnotationTest4 { 

    public static void main(String[] args) { 

     final TreeMap<@Nullable Integer, @Nullable String> treeMap = new TreeMap<>(); 

     treeMap.put(3, "Test1"); 
     treeMap.put(null, null); 

     //This produces the warning 
     final Set<@Nullable Entry<@Nullable Integer, @Nullable String>> set = treeMap.entrySet(); 

     for (final Iterator<@Nullable Entry<@Nullable Integer, @Nullable String>> it = set.iterator(); it.hasNext();) { 

      final Entry<@Nullable Integer, @Nullable String> entry = it.next(); 

      if (entry != null && entry.getKey() == null && entry.getValue() != null) 
       System.out.println(entry.getKey()+" is mapped to "+entry.getValue()); 
     } 

    } 
} 

的警告是:

Null type safety (type annotations): 
The expression of type 
'Set<Map.Entry<@Nullable Integer,@Nullable String>>' 
needs unchecked conversion to conform to 
'Set<[email protected] Entry<@Nullable Integer,@Nullable String>>' 

我試圖@Nullable和的幾種組合@非空。即使? extends正如在這裏類似的情況下建議的:https://bugs.eclipse.org/bugs/show_bug.cgi?id=507779

但是,警告總是隻會移動,但永遠不會完全消失。

更新:

我得到了利用該行擺脫了警告:

final Set<? extends @Nullable Entry<@Nullable Integer, @Nullable String>> set = treeMap.entrySet(); 

但我完全失去了作爲的原因。在我看來,我欺騙驗證人丟失跟蹤或其他內容,代碼真的開始變得醜陋。

煥發出新的代碼:

import java.util.Iterator; 
import java.util.Map.Entry; 
import java.util.Set; 
import java.util.TreeMap; 

import org.eclipse.jdt.annotation.NonNullByDefault; 
import org.eclipse.jdt.annotation.Nullable; 

@NonNullByDefault 
public class NullAnnotationTest4 { 

    public static void main(String[] args) { 

     final TreeMap<@Nullable Integer, @Nullable String> treeMap = new TreeMap<>(); 

     treeMap.put(3, "Test1"); 
     treeMap.put(null, null); 


     final Set<? extends @Nullable Entry<@Nullable Integer, @Nullable String>> set = treeMap.entrySet(); 

     for (final Iterator<? extends @Nullable Entry<@Nullable Integer, @Nullable String>> it = set.iterator(); it.hasNext();) { 

      final Entry<@Nullable Integer, @Nullable String> entry = it.next(); 

      if (entry != null && entry.getKey() == null && entry.getValue() != null) 
       System.out.println(entry.getKey()+" is mapped to "+entry.getValue()); 
     } 

    } 
} 

更新2矮個子粘貼錯誤的代碼。

+0

不應該'set'變量只是'Set >'?條目集中的條目可能不會爲空。 –

+0

我先試了一下。但是錯誤在於,由於@NonNullByDefault,他無法將Set Torge

回答

1

Set<@NonNull X>Set<@Nullable X>這樣的問題類型的核心是不兼容的:兩者都不可分配給另一個。

要智慧:如果你有一個Set<@NonNull X>客戶期望提取非null元素,並且如果設定實際上是Set<@Nullable X>將打破。相反,如果你有一個Set<@Nullable X>客戶期望能夠插入null到集合中,並且如果集合實際上是Set<@NonNull X>將會中斷。

這些因素是相關的,只要你有對付Set<X>「傳統」型的,我們有足夠的知識:它可以被預期爲Set<@NonNull X>Set<@Nullable X>。類型檢查必須考慮到兩種可能性(客戶可能依賴任一假設,因爲例如javadoc可以這樣說)。

通常,在Java中,通過使用有界通配符解決讀寫問題:Set<? extends X>確保讀取訪問總是會產生「至少」X(或更好)。 Set<? super X>確保插入新元素的要求是「至多」X,即任何X或更好的將被接受到集合中(無論實際列表的真實需求是什麼)。

應用上述爲null註釋簡單地說Set<? extends @Nullable X>接受傳統組和支持,設置讀(值將至少@Nullable X,可能會更好,例如,@NonNull X)。 如果您需要插入舊版集,請將其分配給類型爲Set<? super @NonNull X>的變量。這告訴類型檢查器,一個@NonNull X將永遠足夠好插入。

這就是爲什麼Set<? extends @Nullable Entry<..>接受treeMap.entrySet()的結果,實際上它的類型爲Set<Entry<@Nullable Integer, @Nullable String>>。這裏內部類型參數從treeMap的聲明中完全註釋,由於舊版簽名entrySet(),只有頂級類型參數Entry未指定。

最後提到的還提示示例的「真實」解決方案:使用外部註釋來指示entrySet()實際上返回@NonNull Set<@NonNull Entry<K,V>>。有了這個,通配魔法就不需要了。