2012-04-26 92 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更多信息。