2016-11-20 5 views
0

ジェネリックスの上下限でいくつかのサンプルプログラムを試していました。ジェネリックス上限はコンパイルエラーです...しかし、下限は問題ありません。 タイプTのリストをセットに入れて、上限と下限の両方のシナリオを試してみようとしています..ジェネリックス上のワイルドカードでコンパイルエラーが発生する

testUpperBound(T t)メソッドの問題を特定するのに役立ちます。なぜtestLowerBound t)メソッドをコンパイルし、testUpperBound(T t)メソッドはコンパイルしません。私は他の同様のスレッドをチェックしました。しかし、まだ私はそれを明確にしていません。

詳細が必要な場合はお知らせください。

public class TestGenerics<T> 
    { 

     public static void main(String...args) 
     { 
      List<String> list = new ArrayList<>(); 
      list.add("New ArrayList"); 
      new TestGenerics<List<String>>().testUpperBound(list); 
      new TestGenerics<List<String>>().testLowerBound(list); 

     } 

     public void testLowerBound(T t) 
     { 
      Set<? super ArrayList<T>> lowerBoundSet = new HashSet<>(); 
      lowerBoundSet = new HashSet<List<T>>(); 
      ArrayList<T> list = new ArrayList<>(); 
      list.add(t); 
      lowerBoundSet.add(list); // compiles.. 

      out.println(lowerBoundSet); 
     } 

     public void testUpperBound(T t) 
     { 
      Set<? extends List<T>> upperBoundSet = new HashSet<>(); 
      upperBoundSet = new HashSet<List<T>>(); 
      ArrayList<T> list = new ArrayList<>(); 
      list.add(t); 
      upperBoundSet.add(list); // Doesn't compile.. 

      out.println(upperBoundSet); 
     } 

    } 

答えて

0

のためのそのような制限はありません、あなたはあなたの答えを持っている:

Explanation of the get-put principle

これは、Javaのルールで、それがすべてです。 コンパイルが渡された場合、それは安全ではないだろう、なぜ私はあなたのコードで例を与えることがあります。

public void extendsExample(){ 
    Set<? extends List<? extends String>> setOfList = new HashSet<>(); 
    Set<ArrayList<String>> setOfArrayList = new HashSet<>(); 

    // now setOfList var refers to a set 
    // which contains a arraylist of String 
    setOfList = setOfArrayList; 

    // compilation fails 
    setOfList.add(new LinkedList<String>()); 
} 

は、コンパイルが失敗しない想像してみてください。
setOfArrayListインスタンスは、ArrayList個のインスタンスを含むべきセットであり、現在LinkedListエレメントのリストを含んでいます。

setOfArrayListを繰り返した場合、期待どおりにArrayList<String>要素が排他的にはありません。それは安全ではないので、コンパイルに失敗します。 <? superとここでは一例

public void superExample(){ 
    Set<? super ArrayList<String>> setOfArrayList = new HashSet<>(); 

    // compilation ok 
    setOfArrayList.add(new ArrayList<String>()); 
    // new anonymous type derivating from ArrayList 
    ArrayList<String> derivedArrayList = new ArrayList<String>(){ 
    }; 
    // compilation ok 
    setOfArrayList.add(derivedArrayList); 
} 
+0

恐ろしい:) ..最終的に私はそれを明らかにした....デイヴィッドに感謝! 。感謝し、答えを受け入れました。 –

0

<? extends SomeType>でパラメータ化されたコレクションを変更することはできません。ジャバはそれが安全な行動ではないので、それを許可しません。 add()はコレクションを変更するため、コレクションを変更できません。ここで<? super SomeType>

+0

Yaroslavにお返事いただきありがとうございます...しかし、下位クラスと上位クラスのコンパイルでは、下位クラスと上位クラスの違いは何ですか? –

+0

あなたは 'Collection 'に_insert_入れることはできませんが、 ''に挿入することができます。 Iircをキャストして ''から引き続き検索できますが、一般的にはPECS – Rogue

+0

の拡張です。制限の背後にある理由は、タイプ消去に関するものです。 Javaは実行時に正確なパラメータ化を知らないため、修正は上限のあるコレクションに対しては危険な操作です。そのような制限がインターネットにない場合、何がうまくいかないのかという多くの例があります。 –

0

簡単に言えば、我々はリストのタイプはupperBoundSetに含まれているものをコンパイル時に知りません。それはSet<ArrayList<T>>であったり、Set<LinkedList<T>>であったり、他の多くの選択肢の1つであったりする可能性があります。

Set<LinkedList<T>>と判明した場合は、ArrayListを追加することは明らかに悪い考えです。しかし、セットの内容がどのようなタイプであるかわからないので、より安全なオプションをとり、ブロックします。

関連する問題