Here's an example, first, let's define a simple class:
import java.util.List;
public class GenericsTest {
  public GenericsTest() {
    this.stringList = null;
    this.stringField = null;
  }
  private List<String> stringList;
  private String stringField;
}
And now for our test:
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
public class FieldGenericsTest {
  public static void main(String[] args) throws Exception {
    GenericsTest gt = new GenericsTest();
    Field[] fields = gt.getClass().getDeclaredFields();
    for (Field field : fields) {
      // needed to access non-public fields
      field.setAccessible(true);
      Type fieldType = field.getType(); // will be List without generics
      System.out.println("field type: " + fieldType);
      Type genericType = field.getGenericType();
      if (genericType instanceof ParameterizedType) {
        ParameterizedType pt = (ParameterizedType) genericType;
        Type[] types = pt.getActualTypeArguments();
        // since we only have one generic type in our example, that is,
        // List<String> contains only one generic type parameter, the
        // size of this array will only be one.
        Type type = types[0];
        if (type.equals(String.class)) {
          System.out.println("generic type is string: " + type);
        }
      }
      else {
        // fields without generics will fall here
        System.out.println("not a parameterized type: " + genericType);
      }
    }
  }
}
This, by itself, is pretty powerful for the use cases where the generic type needs to be known at run-time.  But, what if you have multiple fields with the same type/generic signature?  That is, we have two fields with the type List<String>.  We can use annotations to distinguish these fields apart and then access the annotations while we're iterating over the fields.  My next post will deal with that use case.





