2016-03-26 3 views
2

Javaでワイルドカードを使用する方法を理解しようとしています。最初のクラスは、第1缶に対しコンパイルできない理由Javaでワイルドカードに関するいくつかの考え方が間違っています

import java.util.List; 
public class WildcardError{ 
    void foo(List<?> i){ 
     i.set(0, i.get(0)); 
    } 
} 

public class WildcardFixed{ 
    void foo(List<?> i){ 
     fooHelper(i); 
    } 
    private <T> void fooHelper(List<T> l){ 
     l.set(0, l.get(0)); 
    } 
} 
  • コンパイラでワイルドカードが表示されるとどうなりますか?それをObjectに変換しますか?ファーストクラスのvoid foo(Object i)、またはvoid foo(List<Object> i)のようになります。
  • タイプ推論は2番目のクラスでどのように機能しますか?あなたがオブジェクト(l.get(0)の結果)を持つ要素を設定した場合、あなたが実際にその型安全に行うことができないので、あなたは、List<String>に合格している可能性が最初の例では

答えて

1

私はこれを行うとき:

import java.util.ArrayList; 
import java.util.List; 

public class Wildcard { 

    public static void main(String[] args) { 
    WildcardFixed wf = new WildcardFixed(); 
    List<Integer> li = new ArrayList<>(); 
    li.add(0); 
    wf.foo(li); 
    System.out.println("Success"); 
    } 
} 

class WildcardError{ 
    void foo(List<?> i){ 
     i.set(0, i.get(0)); 
    } 
} 

class WildcardFixed{ 
    void foo(List<?> i){ 
     fooHelper(i); 
    } 
    private <T> void fooHelper(List<T> l){ 
     l.set(0, l.get(0)); 
    } 
} 

WildcardErrorクラスがメッセージ

方法を設定してコンパイルに失敗したタイプのリストでは、され(int型、キャプチャ#1-の?)引数には適用されません(int、キャプチャ#2)?

もっと単純な英語では、コンパイラはどのタイプのものがiに含まれているかわからない、つまりget()によって返されるタイプがわからず、set()の引数のタイプがわからないため、 set()操作が成功します。

WildcardFixed、しかし、我々はlにあるものの種類、コンパイラを安心させるという理由だけで、getの結果はsetの引数の型と同じ型、T、コンパイルされます。コンパイラはあまり続ける必要はありませんが、それは?以上必要です。

あなたはもっと簡単になります。タイプパラメータTを元のfoo()メソッドに入れると、すべてがコンパイルされて完全に実行されます。

import java.util.ArrayList; 
import java.util.List; 

public class Wildcard { 

    public static void main(String[] args) { 
    WildcardFixed wf = new WildcardFixed(); 
    List<Integer> li = new ArrayList<>(); 
    li.add(0); 
    wf.foo(li); 
    System.out.println("Success WildcardFixed"); 

    WildcardWithT wt = new WildcardWithT(); 
    wt.foo(li); 
    System.out.println("Success WildcardWithT"); 
    } 
} 

class WildcardError{ 
    void foo(List<?> i){ 
     i.set(0, i.get(0)); 
    } 
} 

class WildcardFixed{ 
    void foo(List<?> i){ 
     fooHelper(i); 
    } 
    private <T> void fooHelper(List<T> l){ 
     l.set(0, l.get(0)); 
    } 
} 

class WildcardWithT { 
    <T> void foo(List<T> i) { 
    i.set(0, i.get(0)); 
    } 
} 
2

近視のビット。 2番目の例では

l.get(0)がTである、とl.setに完璧にフィット、

2

このhttps://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html

を説明する良いチュートリアル...

それが安全ではありませんただし、任意のオブジェクトを追加する:

Collection<?> c = new ArrayList<String>(); 
c.add(new Object()); // Compile time error 

cの要素タイプが何を意味するのかわからないので、オブジェクトを追加することはできません。 add()メソッドは、コレクションの要素型であるE型の引数をとります。実際の型パラメータが?の場合、これは未知の型を表します。 addに渡すパラメータは、この未知の型のサブタイプでなければなりません。どんな型であるかわからないので、何も渡すことはできません。唯一の例外はnullです。これはすべての型のメンバーです。

一方、Listを指定すると、get()を呼び出して結果を利用することができます。結果の型は不明な型ですが、常にそれがオブジェクトであることがわかります。したがって、get()の結果をObject型の変数に代入するか、Object型が必要なパラメータとして渡すことは安全です。

関連する問題