2012-12-08 5 views

答えて

7

Javaでは、ジェネリック型の配列を作成するのは簡単ではありません。

単純なアプローチは、コンパイルされない:

public class Container<E> { 

    E[] arr = new E[3]; // ERROR: Cannot create a generic array of E 

} 

ObjectEを交換し、すべてが(他のコンテナの実装に追加の複雑さを犠牲に)十分です。

代替アプローチがありますが、異なるトレードオフのセットがあります。広範な議論のために、How to create a generic array in Java?

+0

あなたはそうです!ありがとうございました!!! – user485553

+3

@ E {] arr =(E [])新しいオブジェクト[3]; ' – Saintali

+1

@Saintali:あなたはできますが、あなたが作業しようとする瞬間に' ClassCastException'を取得しますこの配列。それを試してみてください。 – NPE

2

type erasureを考慮するとご覧(つまり、あなたの例では、このようなEとしてジェネリック型パラメータを編集タイプで削除されているという事実です)、私は、生成されたバイトコードは両方のケースで同様であろうと思います。

メンテナンスの観点から、Objectではなくtypeパラメータを使用すると、コードを読みやすくなります(キャストが制限されるため)。しかしArrayListのAPIは "raw" Objectという配列を公開していないので、単純なJava開発者にとってはそれほど大きな違いはありません:

4

まず最初に、配列オブジェクトの実際の実行時の型Object[]となります。これは、配列が実行時にコンポーネントの型を知っているためです(異なる配列型は実際には実行時に異なる型です)。したがって、配列の作成時にコンポーネント型を指定する必要がありますが、ArrayListオブジェクトは実行時に型引数を認識しません。

それはObject[]として宣言された場合:

private Object[] arr; 
// to create it: 
arr = new Object[3]; 
// to get an element: 
E get(int i) { return (E)arr[i]; } 

インスタンス変数のコンパイル時の型が異なる長所と短所と、Object[]又はE[]のいずれかとして宣言することができ、前記

欠点は、何かを取り出すたびにEにキャストしなければならないということです。つまり、基本的にはジェネリック医薬品前のコンテナとして使用しています。

、それが宣言されている場合はE[]として:

private E[] arr; 
// to create it: 
arr = (E[])new Object[3]; 
// to get an element: 
E get(int i) { return arr[i]; } 

この方法の利点は、あなたは、もはやあなたがそれから物事を取得するときにキャストする必要がないということである - それは型チェックarrの用途に提供し、ジェネリックコンテナのように。不利な点は、論理的にはキャストが存在することです。実行時の型がObject[]であるオブジェクトが作成されていることがわかっているので、EObjectでない限り、E[]のインスタンスではありません。

ただし、Eがクラスのインスタンスメソッド内でObjectに消去されるため、すぐに問題が発生することはありません。問題が発生する唯一の方法は、オブジェクトが何らかの理由でクラスの外部に公開されている(メソッドで返された、パブリックフィールドに置かれたなど)、その型をE[](それはそうではない) :

// This would be bad. It would cause a class cast exception at the call site 
E[] getArray() { return arr; } 

しかしArrayList、そして実際には任意の適切に設計されたコンテナクラスは、そのような外部への内部配列として実装の詳細を公開することはありません。それは他のものの中で抽象化を破るだろう。したがって、このクラスの作成者がこの配列を公開していないことを認識している限り、このようにすることは問題ありません(おそらくコードを見ている次の人を混乱させずに)このようにして増加した型チェックの利点。

関連する問題