13

My project include reflection and i'm currently handling with generic types. I've managed to get the generic type from a List(java.util.List) with:

if(originalField.getGenericType() instanceof ParameterizedType){
    ParameterizedType pt = (ParameterizedType) originalField.getGenericType();
    Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
}

I also have a Collection<String> and it turns out that Collection can NOT be cast to ParameterizedType.

Someone have an idea how to get the String (or whatever type that will be) out of the collection?

I've been reading about java erasure so i'm aware of that, but after getting the generic out of the List, i thought that maybe someone knows another 'trick'.

Thanks.

EDITED: I'm iterating over all of the fields of the class with:

for (Field originalField : someClass.getDeclaredFields())

And then when i'm facing some List<String> Field, with the above code i getting the String as the subClass variable.

Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
Gumba
  • 275
  • 1
  • 3
  • 10
  • 1
    Can you show some more code. Its not clear what's going on here. If the method works for `List`, there is on reason it won't work for `Collection`. – Rohit Jain Oct 08 '13 at 16:25
  • Even if you do get the generic type of the field, there's not much you can do with it. What's the purpose in your case? – Sotirios Delimanolis Oct 08 '13 at 16:27
  • Rohit Jhon - the code does works for List but not for Collection. During runtime it said that Collection cannot be cast to ParameterizedType (as i mentioned in the question). Sotirious Delimanolis - The purpose of this code is to generate code so i nedd the type of the generic – Gumba Oct 08 '13 at 16:35
  • @Gumba. Are you having nested parameterized type? Something like `List>`? And the surname is **Jain**, not **Jhon**. – Rohit Jain Oct 08 '13 at 16:41

2 Answers2

14

Your approach is fine. It should work for both List<String> and Collection<String>. For example see this sample code:

public class Demo {

    List<String> list = new ArrayList<>();
    Collection<String> coll = new ArrayList<>();

    public static void main(String args[]){

        Class<Demo> clazz = Demo.class;
        Field[] fields = clazz.getDeclaredFields();

        for (Field field: fields) {

            Type type = field.getGenericType();

            if (type instanceof ParameterizedType) {

                ParameterizedType pType = (ParameterizedType)type;
                Type[] arr = pType.getActualTypeArguments();

                for (Type tp: arr) {
                    Class<?> clzz = (Class<?>)tp;
                    System.out.println(clzz.getName());
                }
            }
        }
    }
}

this prints out:

java.lang.String
java.lang.String
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
1

As far as I know, Java fully erases the type, so the compiled code has no traces of the value you assigned to parameter types. All the parametric types are translated to concrete types, with type castings and things like that

In the code I've seen so far, when a class need to know the value of its generic type, it forces an object of that type (or the class) to be passed as a parameter. Something like:

class A<T> {
    private final Class<T> parameterType;

    public A(Class<T> parCls) {
        parameterType = parCls;
    }

    public A(T tObj) {
        parameterType = tObj.getClass();
    }
}
Giulio Franco
  • 3,170
  • 15
  • 18