1

Is there a way to get the generic type of the following class at runtime (I will call doSomething() at runtime):

class MyClass<D> extends BaseClass<List<D>> {

    public Class<D> getGenericClass(){
        Type [] ta = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
        Class ty = (Class) ta[0];   // is java.util.List<D> and throws a cast exception

       // TODO I want to know what kind of class "D" is
    }

}

class BaseClass<T>
   T data;
}

I would like to use the MyClass as follows:

MyClass<Foo> instance = new MyClass<Foo>();
Class<Foo> foo = instance.getGenericClass();

The lines of code from above are just to show you the (simplified) scenario I'm facing. If I would instantiate it by hand, then I would already know that I'm using Foo as generic parameter, but thats not the case.

FYI I'm trying to deal with Android Parcelable and to get the correct class loader for readParcelable() by using generics. Concrete: MyClass implements Parcelable. While reading the Parcel I have to specify a classloader like this data = parcel.readArrayList(Foo.class.getClassLoader) and I want to determine that dynamically by using reflections like data = parcel.readArrayList(getGenericClass().getClassLoader())

Is there a way to get that kind of information?

Typically you would just use:

Class type = (Class) (getClass().getGenericSuperclass()).getActualTypeArguments()[0]);

but that returns java.util.List<D>, but I'm interested in what <D> is. Is there a way to dive into that generic type as well?

sockeqwe
  • 15,574
  • 24
  • 88
  • 144
  • thanks, but I the with `getClass().getGenericSuperclass()).getActualTypeArguments();` I get `java.util.List` instead of `java.util.List`. So is, there a way to get evaluate ``? – sockeqwe Apr 19 '15 at 02:30
  • 1
    Do you actually have multiple `ClassLoader`s in your application? I haven't seen a case where the type of the `Class` used to retrieve the `ClassLoader` mattered with `Parcelable`. Can you explain your situation a bit more? – Thorn G Apr 19 '15 at 02:37
  • Good Point, makes it any difference if `MyClass` is part of an `.aar` packed library? – sockeqwe Apr 19 '15 at 02:44
  • No, you cannot find `D` at runtime. This is due to type erasure. Much like the matrix, "there is no D". – Brett Okken Apr 19 '15 at 02:45
  • Thanks, I feared that. However, I thing @TomG is right at this point and it doesn't make any difference which class loader I use on android. But I'm not sure if MultiDex (65K problem) will need another class loader. – sockeqwe Apr 19 '15 at 02:50

1 Answers1

-1

You can try something like (class from java.lang.reflect):

ParameterizedType pt = (ParameterizedType)MyClass.class.getGenericSuperclass();
Type[] t = pt.getActualTypeArguments();

t will contain each generic type of your class.

EDIT: if it's a list, you can reach the list type using something like:

ParameterizedType listType = (ParameterizedType) listField.getGenericType();
Class<?> listClass = (Class<?>) listType.getActualTypeArguments()[0];
DavidL
  • 1,120
  • 1
  • 15
  • 34
  • 1
    That works if you have a variable or a method signature with an actual type defined (i.e. `List`). It can also work in the case of class hierarchy where a super class or interface defines a generic and the actual implementation provides a specific value for that generic (as opposed to still being generic to consumers). This use does not appear to fall into any of those categories. – Brett Okken Apr 19 '15 at 02:44