2012-04-26 16 views
4

クラスフィールドがList<String>かどうかを確認する必要があります。私は、次のコードでそれを行うことを試みた:Reflectionを使用してオブジェクトの汎用タイプを検査するにはどうすればよいですか?

for (Field formField : formClass.getDeclaredFields()) {  
    ... 
    if (formField.getGenericType().equals((Class<List<String>>)(Class<?>)List.class)) { 
    ... 
    } 
} 

は、間違っているコードのようですので、formField.getGenericType().equals((Class<List<String>>)(Class<?>)List.class)戻っても、実際にList<String>あるフィールド上false

もう1つの方法は、フィールドがListformField.getType().equals(List.class)であるかどうか最初にテストし、formField.getGenericType() instanceof ParameterizedTypeで汎用であることを確認し、最後にタイプ引数のクラスをチェックします。

しかし、私はこのチェックを実装する方法がより短いと思います。ある?例から

答えて

4
import java.lang.reflect.Field; 
import java.lang.reflect.ParameterizedType; 
import java.lang.reflect.Type; 
import java.util.ArrayList; 
import java.util.List; 

public class Main { 
    private List<String> strings; 
    private List<ReflectionUtils> list; 
    public static void main(String[] args) { 
     List<Class> genericTypes = ReflectionUtils.getGenericType(Main.class); 
     for(Class genericType : genericTypes) { 
      System.out.println(genericType.getName()); 
     } 
    } 
} 

class ReflectionUtils { 
    public static List<Class> getGenericType(Class clazz) { 
     List<Class> genericTypes = new ArrayList<Class>(); 
     Field[] fields = clazz.getDeclaredFields(); 
     for(Field field : fields) { 
      Class c = getGenericType(field); 
      if(c != null) { 
       genericTypes.add(c); 
      } 
     } 
     return genericTypes; 
    } 

    public static Class getGenericType(Field field) { 
     Type genericType = field.getGenericType(); 
     if(genericType instanceof ParameterizedType) { 
      ParameterizedType parameterizedType = (ParameterizedType) genericType; 
      return (Class) parameterizedType.getActualTypeArguments()[0]; 
     } 
     return null; 
    } 
} 

出力:

java.lang.String 
ReflectionUtils 
3

あなたはGuavaの新しいTypeTokenクラスを使用することができます(バージョン12.0に含まれます...それのリリース候補は、Mavenの中で現在利用可能です)クラスフィールドが実際List<String>、ないList<T>または0123として宣言されている場合にのみ動作していること

for (Field formField : formClass.getDeclaredFields()) {  
    ... 
    TypeToken<?> type = TypeToken.of(formField.getGenericType()); 
    if (type.equals(new TypeToken<List<String>>(){}) { 
    ... 
    } 
} 

注:このような。あなたはそれがArrayList<String>List<String>を実装する任意の他のタイプと一致する場合は、代わりに次のチェックを行うことができます:

if (new TypeToken<List<String>>(){}.isAssignableFrom(type)) { 

それが宣言クラスにList<T>として宣言されてList<String>フィールドがありますかどうかを確認するために実際に可能ですあなたが扱っているクラスがその型に何を指定するサブクラスであるならば、Tです。この例を見てみましょう:

class Foo<T> { 
    private List<T> list; 
    ... 
} 

class StringFoo extends Foo<String> { // T is specified in here 
    ... 
} 

TypeToken<StringFoo> stringFooType = TypeToken.of(StringFoo.class); 
// iterate through superclasses of StringFoo 
for (TypeToken<?> superclass : stringFooType.getTypes().classes()) { 
    for (Field field : superclass.getRawType().getDeclaredFields()) { 
    // actually resolves T to String for the List<T> field using info from 
    // StringFoo's type 
    TypeToken<?> type = stringFooType.resolveType(field.getGenericType()); 
    if (new TypeToken<List<String>>(){}.isAssignableFrom(type)) { 
     System.out.println("List<String> found!"); 
    } 
    } 
} 

利用可能TypeTokenhereの詳細情報があります。