2011-07-28 26 views
4

下記のとおり一般的な方法は:ジェネリックメソッド有界型パラメータと型消去

私は消去時に推定
static <E, K extends E> void someMethod(K k, E[] e) {} 

、消去タイプは次のようになります。どのようにでしょうtypeパラメータ

static void someMethod(Object k, Object[] e) {} 

興味があるだけタイプ消去後の制約を知っていますか?その型パラメータKはE?

答えて

8

あなたは消去について正しいです。実際には、ランタイムは制約について知らない。コンパイラのみが行います。

+3

それ以外の場合はあまり消去されません。 –

2

あなたのタイプ消去された署名は正しいです。ただし、メソッドの制約はコンパイル時に消去されません。コンパイル時に使用されるメタデータにエンコードされます(リフレクション*でアクセスできますが、通常は実行時には使用されません)。その後、あなたはget(...)メソッドを呼び出すことになりますあなたがStringArrayListをパラメータあれば、あなたのコードでは、

public Object get(int index) 

しかし:

public E get(int index) 

型消去して次のようになります。たとえば、クラスjava.util.ArrayList<E>はメソッドを持っていますタイプ消去にもかかわらず、結果をStringにキャストする必要はありません。

これは、クラスまたはメソッド呼び出しをパラメータ化するときとは異なります。提供されたパラメータ化は、コンパイル時に完全に消去されたです。たとえば:


*

ArrayList myList = new ArrayList(); 
java.lang.reflect.Typeインスタンスを返す反射法を使用して行うことができる反射を経由して、実行時にこの情報へのアクセス:コンパイル後

ArrayList<String> myList = new ArrayList<String>(); 

は同等です。たとえば、実行時にメソッドの制約を取得するには、java.lang.reflect.MethodgetGenericParameterTypes()メソッドを呼び出すことができます。この返された情報を処理することにより、実行時に制約を判別することができます。

2

私は実際には、あなたのタイプの制約

static <E, K extends E> void someMethod(K k, E[] e) {} 

static void someMethod(Object k, Object[] e) {} 

として(コンパイル時)正確同じ効果があり、それを注意したいあなたはドンが」someMethod("foo", new Integer[3])を呼び出して試してみてください私を信じていない。コンパイラは、EK両方のパラメータとしてObjectを推測することが有効であるため

これは(任意KオブジェクトもObjectのインスタンスであり、そして任意E[]オブジェクトもObject[]のインスタンスであるため(その配列を覚えています型はJavaでは共変です))。

これはJava Genericsの一般的な落とし穴です。たとえば、Arrays.fill()メソッドのシグニチャはstatic void fill(Object[] a, Object val)です。それをさらに制限することはできません。

関連する問題