2015-01-02 11 views
7

私は最近Javaジェネリックスを学んでいますが、 "Java Generics FAQ"に行きます。Javaジェネリックスワイルドカードの混乱

ワイルドカードのパラメータ化された型に関する疑問(#304)は私には分かりませんが、助けていただければ幸いです。

コード例:

boolean equal = box.equalTo(box); 
equal = box.equalTo(new Box<String>("abc")); 

おかげ

+4

エラーは何を意味し、何について理解していますか? –

+0

@SotiriosDelimanolisはequalTo()のパラメータがボックスであると考えていて、ボックスが引数として "box"と "new Box (" abc ")"を受け入れることができない理由を理解していません。 – foolhunger

+0

エラーと言うと、コンパイラエラーまたはランタイムエラーを意味しますか? – smac89

答えて

7
Box<?> box = new Box<String>("abc"); 
box.put("xyz");  // error 
String s = box.take(); // error 
  1. を、あなたはポリモーフィズムを使用しています。だから、時間をコンパイル時に、ボックスオブジェクトのタイプは、Box<?>

  2. Type<?>これは未知のワイルドカードと呼ばれています。タイプされているボックスのタイプがわからないので、そのオブジェクトからのみ読み取ることができ、読み取られたオブジェクトはObjectインスタンスとしてのみ使用できます。だからbox.put("xyz")が受信エラーで、String s = box.take()が受信エラーです。第二に

は:

boolean equal = box.equalTo(box); 

equalToはないBox<?>Box<T>受信されます。上で説明したように、Tはクラスを表しますが、?は未知のワイルドカードを意味し、これらの2つの用語は同じではありません。

あなたが知っておくべき他のポイント。 Javaでは、ジェネリックはコンパイル時です。 C#のような他のものと対照的に、ジェネリックは実行時にあります。ここで

は、ワイルドカードについての参照リンクである:このヘルプ:)

5

equalTo方法はBox<T>、ないBox<?>取ります

class Box<T> { 
    private T t; 
    public Box(T t) { this.t = t; } 
    public void put(T t) { this.t = t;} 
    public T take() { return t; } 
    public boolean equalTo(Box<T> other) { return this.t.equals(other.t); } 
    public Box<T> copy() { return new Box<T>(t); } 
} 

class Test { 
    public static void main(String[] args) { 
    Box<?> box = new Box<String>("abc"); 
    box.put("xyz");  // error 
    box.put(null);  // ok 

    String s = box.take(); // error 
    Object o = box.take(); // ok 

    boolean equal = box.equalTo(box); // error {confused} 
    equal = box.equalTo(new Box<String>("abc")); // error {confused} 

    Box<?> box1 = box.copy(); // ok 
    Box<String> box2 = box.copy(); // error 
    } 
} 

が失敗すると呼ばれる理由は、以下の2つの方法を把握することはできません。 Box<?>のオブジェクトを持っている場合、Box<String>またはBox<?>をパラメータとしてequalToに設定することはできません。これは、2つのボックスのタイプが同じでない可能性があるからです(T)。

コンパイラはコンパイル時にオブジェクトの静的型を使用することに注意してください。

だから、これは失敗します。

Box<?> b = new Box<String>(); 
b.equalTo(new Box<String>("abc"); 

しかし、これはしません:OOPで

Box<String> b = new Box<String>(); 
b.equalTo(new Box<String>("abc"); 
3

が理由と呼ばれる2つの方法の下に把握することはできませんJava wildcard

希望はこれがあるので、彼らは失敗

を失敗しますワイルドカードの仕組み

ワイルドカードは「わからない種類」を表します。

もっと簡単なクラスを作ってみましょう。

class Holder<T> { 
    private T obj; 

    void set(T obj) { 
     this.obj = obj; 
    } 

    T get() { 
     return obj; 
    } 
} 

Holder<?>がある場合、私たちはそれにアクセスするための特別なルールを持っています。特に、一般的な引数を持つメソッドを呼び出すことはできません。これは、私たちがどんなタイプのものであるかわからないからです。そうすることは危険です。

class Holder<?> { 
    private X obj; 

    void set(X obj) { 
     this.obj = obj; 
    } 

    Object get() { 
     return obj; 
    } 
} 

Xは、我々はそれはもうあるかわからないので、タイプは立ち入り禁止私たちにあることを意味:私たちはHolder<?>を持っている場合は

は、我々は(概念的には)のようなものを持っています。

  • get戻っObjectそれは我々がobjがあることを確認することができます唯一のクラスであるため
  • set私はこれがあなたのequalToが元々のように宣言されたのであれば奇妙に思えるかもしれないと仮定し、すべての

で呼び出すことはできません

public boolean equalTo(Box<?> other); 

あなたはそれを呼び出すことができます。ただし、ワイルドカードはT?に置き換えるだけでは機能しません。

4
  • Box<?>は「不明のボックス」です。
  • Box<? extends String>
  • は「少なくとも文字列であるものの箱」
  • Box<String>は間違いある「文字列の箱」になります。
  • "不明のボックス"があり、その中に型(Stringなど)を入れようとします。コンパイラは確信していません。その不明の箱です。実際にIntegersだけを受け入れた場合はどうなりますか?
  • nullを「不明のボックス」に入れることはできますか?確かに。
  • 「不明のボックス」から「取得」するものは何ですか?少なくともオブジェクト。

    Box<?> box = new Box<String>("abc"); 
    

    はその約<String>を忘れるとboxは "不明の箱" であると仮定するコンパイラを求め、ということを考えると

。表示されるエラーは、コンパイラが引き続き引数の型チェックを行うことができないことを示します。指定された型が未知であるかどうかをチェックすることはできません(nullを除く)。