2012-04-26 97 views
4

我需要检查一个类的字段是否为List<String>。我试着这样做与下面的代码:如何使用反射检查对象的通用类型?

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

这似乎是一个错误的代码,因为formField.getGenericType().equals((Class<List<String>>)(Class<?>)List.class)回报false甚至,它实际上是一个List<String>领域。

另一种方法是先测试一个字段是否为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)像这样:

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

注意,如果类字段作为List<String>,不List<T>或0123居然宣称这样做才有效。如果你希望它匹配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!"); 
    } 
    } 
} 

有上TypeToken可用here更多信息。