2017-02-22 17 views
2

私はジェネリックのクラスを持っています。私は、ジェネリック型の情報が実行時に削除されることを知っていますが、これはバウンド型です。コンパイル時にjava.lang.Objectがバインドされた型に置き換えられたと私は考えました。すべてが常に少なくともAnimalであることを知っているなら、コンパイラはそれをObjectのままにしていますか?私が欲しいのと同じようにこの仕事をするために欠けているものがありますか?具体的には、その最後のforループのメインメソッドは、コンパイル時に問題があります。有界ジェネリック型の消去とは何ですか?

ありがとうございます!

public static void main(String[] args) throws Exception { 

    Litter<Cat> catLitter = new Litter<>(); 
    for(Cat cat : catLitter) {} 

    Litter<Animal> animalLitter = new Litter<>(); 
    for(Animal animal : animalLitter) {} 

    Litter litter = new Litter(); 
    for(Animal animal : litter) {} // Type mismatch: cannot convert from element type Object to Animal 
} 

public class Litter<T extends Animal> implements Iterable<T>{ 
    @Override public java.util.Iterator<T> iterator() { 
     return new LitterIterator(); 
    } 

    class LitterIterator implements java.util.Iterator<T> { 
     @Override public boolean hasNext() { return false; } 
     @Override public T next() { return null; } 
    } 
} 

public class Animal {} 
public class Dog extends Animal{} 
public class Cat extends Animal{} 
+3

すべてのコンパイラ警告をオンにすると、 'litter'の生の型を使用していることがわかります。これは基本的にコンパイラにその文のジェネリックの存在を無視させます。 – VGR

+0

タイプが指定されていない場合は、すべての汎用情報が削除されます。オブジェクトはそのままです。 – Bohemian

+0

それはあまり単純ではありません@ボヘミアン。有界型は規則を少し変更します。 Sotiriosが示しているように、TがAnimalを継承しているときに通常Tを返すインスタンスメソッドは、生の型のAnimalを返します。私の混乱は、IteratorがAnimalにパラメータ化されていない理由です。 – bmauter

答えて

4

必須リダイレクト:

あなたが期待している行動が

public class Litter<T extends Animal> implements Iterable<T>{ 
    public T get() {return null; /* or whatever */} 
    ... 
} 

012のようなものに適用されます Litterので

raw type

コンストラクタ(§8.8)、インスタンスメソッドの種類(§8.4、§9.4)、または 非静的フィールドである(§8.3)のその スーパークラス又はスーパーインターフェースから継承されていない生のタイプCC

に対応する一般的な宣言に にそのタイプの消去に対応する生の型であります

以降、

タイプ変数(§4.4)の消去は、その左端の境界の消去です。次いで

Litterタイプを使用してコーディングする

public Animal get() {...} 

として現れるget方法。 Litter#iterator()として

しかし、その戻り型はIterator<T>であり

ので、パラメータ化された型(§4.5)G<T1,...,Tn>の消去は|G|あります。

その消去は、ちょうどIteratorです。 Iteratornext()方法は、そのように明らかにその戻り値をタイプAnimalの変数に割り当てることができない

public Object next() {...} 

に消去されます。

私が望むようにこの作品を作ることができないものがありますか?

生の種類はありません。

+0

ありがとうございます。この回答は非常に役に立ちます。私はまだこれがいかに意味があるかと苦闘している。 JLSの最初の引用は、get()メソッドがあなたの例のようにObjectではなくAnimalを返すと考えるようにします。 生のLitterオブジェクトのget()メソッドはAnimalを返しますが、iterator()メソッドは(反復子の代わりに)生のIteratorを返します。これはどういう意味ですか?私がEclipseで利用できるメソッドのリストを見ているとき、これは混乱します。 – bmauter

+0

一般的なコードの前提を壊すので、Raw型はJavaで完全に削除する必要があります。これはおそらく後方互換性のために追加されましたが、私の意見ではそれは欠落した決定でした。 – MaxZoom

+0

@bmauter申し訳ありませんが、私はあなたのコメントを見ていませんでした。これは 'T'(Animal')の消去と' Iterator'である 'Iterator 'の消去との違いです。そして、 'Iterator'の' next'も生の値でアクセスしているので、消去しなければなりません。型パラメータ 'E'の消去は無限であるため、' Object'です。 –

関連する問題