2013-04-17 5 views
6

こんにちはすべて:)私はクラス内で正しいコンストラクタを選択しようとしています。ここでは、コードは次のようになります。クラスにジェネリックを使用している特定のコンストラクタがあるかどうかを実行時に確認する

Constructor[] constructors = targetClass.getConstructors(); 
Constructor goodConstructor = null; 
for (Constructor constructor : constructors) { 
    Class[] parameterTypes = constructor.getParameterTypes(); 
    if (parameterTypes.length = 1 && parameterTypes[0].equals(Map.class)) {//here 
     goodConstructor = constructor; 
    } 
} 

私はMap.classからMap<String, String>.classに切り替えたいです。ジェネリックはコンパイル時のみであることを漠然と覚えているので、これがコンパイラが不平を言っている理由です。クラスに正しいコンストラクタがあることを実行時にどのように確認できますか?

敬具

答えて

8

代わりgetGenericParameterTypes()使用する:あなたは、それはもはや一致しませんMap<String, Integer>を取るためにMyClass()を変更した場合、今

public class FindConstructor { 

    public static void main(String[] args) throws IOException { 
     for (Constructor<?> constructor : MyClass.class.getConstructors()) { 
      Type[] parameterTypes = constructor.getGenericParameterTypes(); 
      if (parameterTypes.length == 1 && parameterTypes[0] instanceof ParameterizedType) { 
       ParameterizedType parameterizedArg = (ParameterizedType) parameterTypes[0]; 
       if (parameterizedArg.getRawType() != Map.class) { 
        continue; 
       } 

       if (parameterizedArg.getActualTypeArguments()[0] != String.class) { 
        continue; 
       } 

       if (parameterizedArg.getActualTypeArguments()[1] != String.class) { 
        continue; 
       } 
      } 
      System.out.println("found constructor " + constructor); 
     } 
    } 
} 

class MyClass { 
    public MyClass(Map<String, String> map) { 
    } 
} 

を。

GuavaのTypeTokenでは、匿名クラスを使用してパラメータ化されたTypeを作成して比較することができます。

Type mapStringString = new TypeToken<Map<String, String>>(){}.getType(); 
for (Constructor<?> constructor : MyClass.class.getConstructors()) { 
    Type[] parameterTypes = constructor.getGenericParameterTypes(); 
    if (parameterTypes.length == 1 && parameterTypes[0].equals(mapStringString)) { 
     System.out.println("found constructor " + constructor); 
    } 
} 
+0

私の答えを削除しました。 「ジェネリック使用型消去」の回答で返事をする前に、もっと慎重にしなければならない!私は、あなたがこれをやっているなら、あなたのデザインに間違いがあると確信しています! :) – James

0

クラスはjavaではそのようには動作しません。実行時にクラスをパラメータ化することはできません。インスタンスのみ。 Mapのジェネリック実装ごとに別々のクラスを用意するのではなく、Map.classが1つしかありません。次のコードはこれを明確にするのに役立ちます:

Map<String,String> m1 = new HashMap<>(); 
    Map<Object,Long> m2 = new HashMap<>(); 

    System.out.println(m1.getClass() == m2.getClass());//prints "true" 
+0

これは 'Class'にも当てはまりますが、Javaでは型パラメータ、つまり' ParameterizedType'(私の答えを見てください)を持つ型の表現がサポートされています。型パラメータは、しばしばコンパイルされます(初心者の場合は、汎用フィールドまたはパラメータを宣言するたびにコンパイルされます)。その情報がクラスファイルで利用できなかった場合は、ジェネリックスを使用するクラスに対してコンパイルすることはできません。 –