尝试获取泛型类时ClassCastException

时间:2015-05-01 13:54:06

标签: java generics reflection

我尝试使用this answer中给出的代码。我这样做了:

public class ListClass<T> {
  private class ObjectFactory<T> {
    //This should the the class of generic type T which is what I need
    public final Class<T> cls;
    @SuppressWarnings ("unchecked")
    public ObjectFactory()
    {
      //This three lines are from the linked answer - I don't really understand them
      Type type = getClass().getGenericSuperclass();
      ParameterizedType paramType = (ParameterizedType) type; //java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
      cls = (Class<T>) paramType.getActualTypeArguments()[0]; 
    }
    public T createNew(... some parameters ...) {
      return (T)new Expression(cls, "new", new Object[]{... some parameters ...}).getValue();
    }
  }
  public final ObjectFactory<T> factory = new ObjectFactory<T>();

  public generateItem() {
    //let add() be method that adds item of type T to this list
    this.add(factory.createNew(... some parameters ...));
  }
}

我错了什么?

2 个答案:

答案 0 :(得分:3)

只有使用如下具体参数对类进行参数化时,此方法才有效:

class Sub extends Super<String> {}

然后通过扩展:

new Super<String>() {}

但不是这样:

class Sub<T> extends Super<T> {}

而不是这样:

<T> Super<T> m() {
    return new Super<T>() {};
}

使用getActualTypeArguments的能力是类的属性,而不是实例,因此该类需要实际的类型参数才能使用它。

根据你的编辑,我建议你做的是为此创建一个辅助程序:

static <T> Class<T> getActualTypeArgument(Class<?> clazz, int i) {
    Type superclazz = getClass().getGenericSuperclass();
    ParameterizedType paramType = (ParameterizedType) superclazz;

    @SuppressWarnings("unchecked")
    final Class<T> actual =
        (Class<T>) paramType.getActualTypeArguments()[i];
    return actual;
}

然后在ListClass

上使用此功能
class ListClass<T> {
    private ObjectFactory<T> factory = new ObjectFactory<T>(
        getActualTypeArgument(this.getClass(), 0));
}

并在例如{}中创建ListClass以下方式:

ListClass<GameObject> list =
    new ListClass<GameObject>() {};

还要考虑只传递Class<T>

class ListClass<T> {
    private ObjectFactory<T> factory;

    ListClass<T>(Class<T> type) {
        factory = new ObjectFactory(type);
    }

    static <T> ListClass<T> of(Class<T> type) {
        return new ListClass<T>(type);
    }
}

ListClass<GameObject> list =
    ListClass.of(GameObject.class);

答案 1 :(得分:2)

Class#getGenericSuperClass()上引用文档:

  

回答代表接收者超类的类的类型。对于表示基类型,接口和java.lang.Object的类,该方法应答null。

ObjectFactory<T>课程中调用它将返回Object类型,而不是ParameterizedType