2012-03-12 6 views
8

私は、一般的な配列は、このようなようにインスタンス化できないことを十分に承知しています:ジェネリック配列をインスタンス変数として宣言できるのはなぜですか?

data = new Entry<K, V>[]; 

これはエラーになります:

Cannot create a generic array of Entry<K,V> 

は、なぜ私はインスタンス変数を宣言するために許可されていますエラーのないジェネリック型アレイですか?

private Entry<K, V>[] data; 
+3

一般的な型の配列を宣言すると、それをそのまま*使用する*意図*が宣言されます。コンパイラ*はジェネリック型をチェックすることができず、配列内のジェネリック型を持つ型システムを簡単に破ることができます。コンパイラはチェックできない操作をしているときに指示します。最適な解決策:コンパイラで型の一貫性をチェックする場合は、配列を避けてください。 –

+0

Angelika Langerの[Generics FAQ](http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#Can%20I%20create%20an%20array%20whose%20component%20type%20is%20a%20concrete%も参照してください) 20インスタンス化%20of%20a%20パラメータ化%20type?) – McDowell

答えて

4

原則として、Joachim Sauerのコメントはすでにあなたの答えですが、私は少し詳しく説明します。

Sun(Oracle)は、一般的な変数ポインタが型と互換性のないオブジェクトを指している場合に常に発生するメモリー汚染と呼ばれる現象を認識しています。これは、次のコードで、たとえば強制することができます:あなたがそのコードで作業を始めると

List<String> list = new ArrayList<String>(); 
List<Number> numberList = (List<Number>)(List)list; 

明らかに、あなたは、ClassCastExceptionsを見て開始します。これはGenericsを設計するときにSunにとって完全に大丈夫でした。なぜなら、あなたはRawType/Unchecked変換の義務的警告を得るからです。この警告が発行されるたびに、あなたはコードがあります。これは100%型チェックではなく、メモリ汚染が発生する可能性があります。

ジェネリックスの全体的な設計原則は、考えられるすべてのメモリ汚染がそのような警告によって示されることです。このため、汎用配列の作成は禁止されています。ここでは、それがなかったと仮定するとどうなるかです:あなたは警告なしと互換性の理由のためにそこにメモリ汚染を持っています

List<String>[] array = new List<String>[5]; 
Object[] oArray = array // this works without warning and has to for compatibility 
List<Object> oList = new ArrayList<Object>(); 
oArray[1] = oList; 

、警告が発生することができません。これがSunがジェネリックタイプの配列を禁止することに決めた理由です。ただし、未確認の変換警告が表示されているため、変数が宣言されている可能性があります。これはSunが望むすべてのものです。汚染が発生した場合の警告です。

2

コンパイラおよび/またはJITではジェネリック型を推測できる必要があるためです。

Entry<K, V>[]のインスタンスを作成しようとすると、コンパイラはK型とV型​​を推論することができないため、実際のオブジェクトを作成することができません(つまり、コンパイラは正しいコンストラクタ)。

ただし、タイプがEntry<K, V>[]のメンバーの場合は、一般的なタイプの参照に過ぎません。
正しいタイプは、使用されるときに割り当てられる実際のタイプに基づいて推定されます。また、実際の型を参照するため、ancコンストラクタを呼び出すすべてのメソッドは、参照される型によって決定されます。

関連する問題