微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java Generics:如何为泛型类型指定Class类型?

我有一个指定为:MyClass< U>的POJO,其中U是泛型类型参数.
我正在尝试编写一个实用方法,它接受类引用Class< T>并填充Map< String,T>类型的地图(接受填充的地图).

这种方法实现如下:

static void populateMap(Map<String,T> map,Class<T> type) {

    ...

    // Parses into the specified type and returns an object of that type.
    T obj = parse(...,type);
    map.put (key,obj);
    ...

    return map;
}

编译好了.在我的调用者中,我尝试使用任何MyClass实例(无论类型)填充地图作为值.因此我使用以下代码

// Loses type information
Map<String,MyClass<?>> m = new HashMap<>();
populateMap(m,MyClass.class);

这不编译.编译错误

The method populate(Map<String,T>,Class<T>) in the type … is not applicable for the arguments (Map<String,MyClass<?>>,Class<MyClass>)

我怎样才能解决这个问题?

解决方法

在这种情况下,对Class< MyClass<?>>进行未经检查的强制转换应该是安全的:
// This is okay because we're switching to a type with an unbounded wildcard -
// the behaviors of Class.newInstance and Class.cast are still safe.
@SuppressWarnings("unchecked") 
Class<MyClass<?>> classWithNarrowedType =
        (Class<MyClass<?>>)(Class<?>)MyClass.class;
populateMap(m,classWithNarrowedType);

这是一个非常重要的解决方案,特别是如果你有很多像这样的调用网站,但是没有解决文字用原始类型参数化的事实,使它们被用作参数化类型的工厂,如MyClass< T>本质上很尴尬.

一个可能更清晰的解决方案是将populateMap与类文字的使用分离:

interface Parser<T> {

    T parse();
}

static void populateMap(Map<String,Parser<T> parser) { ... }

...

Map<String,MyClass<?>> m = new HashMap<>();
Parser<MyClass<?>> myClassparser = new Parser<MyClass<?>>() {
    @Override
    public MyClass<?> parse() {
        return parse(...,MyClass.class);
    }
};
populateMap(m,myClassparser);

另外,我建议使用更灵活的签名(有关详细信息,请参阅What is PECS (Producer Extends Consumer Super)?):

static void populateMap(Map<String,? super T> map,Parser<T> parser)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐