2013-07-19 14 views
12

私はクラスがある場合:私は別のクラスからそのメソッドを使用しようとするとJavaジェネリックの未加工クラスは、型パラメータが指定されていないときにジェネリックをすべて消去するのはなぜですか?

public class GenericClass<TBlah extends Number> { 
    public List<String> getList() { 
     return null; 
    } 
} 

を:私はへのループのために上の行を変更するまで

public class OtherClass { 
    public void test() { 
     GenericClass a = null; 
     for (String s : a.getList()) { 

     } 
    } 
} 

なぜa.getList()List<Object>を返すん。

GenericClass<Number> a = null; 

その時点a.getListで、()、それが何をすべきようなList<String>を返しますか?

編集:getList()で指定された契約が、変数「a」をどのように宣言するかによって、なぜ影響を受けるのか分かりません。 getList()は常にList<String>を返しますが、それは何でも問題ありませんTBlahです。

+1

なぜ、それを「ヌル」に初期化するのですか? – fge

+0

@fgeシンプルさ。私が思う問題とは無関係です。 – Xenoprimate

+7

これは、JLSの作家が選択したものですから。 AFAIK、理由は、あなたが生の型を使用する場合、あなたはジェネリック型を気にしないということです。解決策は、生の型の使用を避けることです。 –

答えて

8

これはジェネリックスが機能する方法です。あなたがListと宣言したときにジェネリックスの前にそれがObjectのリストであったことを忘れないでください。あなたは/ Objectをつけることを期待されていました。あなたは正しいタイプであなたのオブジェクトを得るために投げ込まれました。実際にはまだです。実行時のObjectのリストです。

ジェネリックスは、コンパイル時にという警告が表示されていないと仮定して、コンパイル時に安全性をタイプする方法です()。実行時にはList<String>はありません。ちょうどListがある。コンパイラによって自動的にキャストされるので、キャストなしでString s = list.get(i)と書くことができます。

GenericClass aを宣言すると、生の型が宣言されているので、コンパイラはa.getList()が返すと思われる型を知る方法がありません。したがって、それはObjectを使用します。今すぐGenericClass<Number> a = null;を宣言すると、コンパイラはa.getList()の期待する型を知り、それを使用します。

は編集:コンパイラは、あなたが署名の契約を尊重している場合にのみ期待するかを知ることができることを明確にしなければならない(すなわちGenericClass<Number>の場合のように)。契約を尊重しない場合(つまり、extends Numberではない生の種類を使用している場合)、契約はもう適用されません。コンパイラは、型情報が存在しないかのように動作します。コンパイラは、ジェネリック以前の時代に作成されたコードとの下位互換性も維持する必要があることを忘れないでください。

+0

それは賢明です。しかし、なぜコンパイラはa.getList()が返すべきものを知らないのでしょうか?それはメソッドシグネチャの中にあります。 TBlahを宣言しても、それは変わりません...なぜ、私は生の型を使用することが重要ですか? – Xenoprimate

+0

Thatsが正しくありません。署名の中にはありません。署名は「数を伸ばしてくれる」と言う。 'Object'が' Number'を拡張しないので、署名がもう適用されないように、生の型(つまり単純な 'Object')を使用しました –

+1

しかし、getList()のList の戻り値の型は、私がTBlahすることが。ではなぜそれは問題なのでしょうか? – Xenoprimate

-2

あなたは、参照すると、参照が同じtype.likeのものでなければならないリストにプレースホルダ/参照が必要

一覧<文字列>のx = a.getList();

関連する問題