2016-11-22 8 views
0

このサンプルコードで警告を取り除く方法。TreeMapのeclipseネオンで "Null型安全"警告を取り除く方法

私は、Java 1.8とEclipseのネオンを使用して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()); 
     } 

    } 
} 

警告がある:私は@Nullableとのいくつかの組み合わせを試してみました

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>>' 

@ NonNullable。同じような場合には、? 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 > 'でなければなりませんか?エントリセット内のエントリはおそらく決してnullにはなりません。 –

+0

まずそれを試しました。しかし、そのエラーは、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以上のものがセットに受け入れられる(実際のリストによる実際の要件が何であれ)。

ヌルアノテーションに上記を適用するには、従来のセットを受け入れ、セットからの読み込みをサポートするために単に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の宣言から完全に注釈され、の従来の署名のために、最上位型引数Entryのみが指定されていません。

最後の例では、例の「実際の」解決策を示唆しています。entrySet()が実際に@NonNull Set<@NonNull Entry<K,V>>を返すように外部アノテーションを使用します。これで、ワイルドカードの魔法は必要ありません。

関連する問題