在运行时获取泛型类名

时间:2013-04-02 17:50:14

标签: java reflection

我的应用程序正在抛出

java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType

对于此代码:

public class DsMap<K,V> implements Map<K, V>{
    protected Class<K> kClazz;
    protected Class<V> vClazz;  

    // Called during DS.getMap(mapName) method
    public DsMap(String name) {
        ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
        Type typeK = genericSuperclass.getActualTypeArguments()[0];
        Type typeV = genericSuperclass.getActualTypeArguments()[1];

        if (typeK instanceof Class) {
            this.kClazz = (Class<K>) typeK;
        } else if (typeK instanceof ParameterizedType) {
            this.kClazz = (Class<K>) ((ParameterizedType)typeK).getRawType();
        }

        if (typeV instanceof Class) {
            this.vClazz = (Class<V>) typeV;
        } else if (typeV instanceof ParameterizedType) {
            this.vClazz = (Class<V>) ((ParameterizedType)typeV).getRawType();
        }           
    }
}

我想要实现的是在运行时获取KV的类名:

这样做:

Map<String,String> dsMap = DS.getMap(mapName);

对于java.lang.StringkClazz的类名,我将获得vClazz,或者获取参数化的任何类名(不实例化Class<K>Class<V>)< / p>

我的代码可能有什么问题?

3 个答案:

答案 0 :(得分:1)

参数化类型表示泛型类型的具体实现。您可以像考虑模板文档之间的关系一样考虑泛型和参数化类型之间的关系。模板会告诉您填写信息的位置,文档中包含实际填写的信息。在您的示例中:

public class DsMap<K,V> implements Map<K, V>

DsMapMap都是通用类型(或模板)。它们的实际泛型参数不是由类本身指定的,因此编译器不会捕获它们。换句话说,它们的通用信息在运行时不可用。

为了在运行时捕获实际的通用参数,这些参数需要是类签名的一部分。例如,这个简单的类扩展可以工作:

public class DsMapIntegerString extends DsMap<Integer, String>

因为您提供了具体参数,getClass().getGenericSuperclass()返回的类型实际上是参数化类,您的代码将不再失败。

答案 1 :(得分:0)

DsMap实现了一个通用接口(Map<K,V>),但它没有扩展泛型类。因此,getClass().getGenericSuperclass()会返回对java.lang.Object的引用,该引用无法转换为ParameterizedType

(ParameterizedType) getClass().getGenericSuperclass()技巧仅适用于 1)子类扩展了泛型类 2)子类在编译时声明其类型参数

e.g:

public abstract class DsMap<K, V> implements Map<K, V> {

...

public class StringIntDsMap extends DsMap<String, Integer> {

...

然后,getGenericSuperclass()将返回DsMap,可以转换为ParameterizedType,并且可以转换从Type[]返回的getActualTypeArguments()数组中的条目到Class

不幸的是,这不是一个非常普遍的情况。我经常使用它在单元测试之间共享代码(我可以在编译时声明泛型类型)。但它并没有推广到运行时类型不可用的情况。

答案 2 :(得分:0)

目视检查说尝试改变:

static public class DsMap<K, V> implements Map<K, V> {

static public class DsMap<K, V> extends HashMap<K, V> {