Java泛型:如何为泛型类型化的类指定类类型? [英] Java Generics: How to specify a Class type for a generic typed class?

查看:684
本文介绍了Java泛型:如何为泛型类型化的类指定类类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a POJO specified as: MyClass<U>, where U is the generic type parameter. I am trying to write a utility method which accepts a class reference Class<T> and populates a map of type Map<String, T> (accepts the map to populate).

此方法的实现方式如下:

This method is implemented like:

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实例(与类型无关)作为值填充映射.因此,我使用以下代码:

This compiles fine. In my caller, I attempt to populate a map with any MyClass instance (irrespective of type) as the value. Hence I use the following code:

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

这不能编译.编译错误:

This does not compile. Compilation error:

类型...中的方法populate(Map<String,T>, Class<T>)不适用于参数(Map<String,MyClass<?>>, Class<MyClass>)

我该如何解决?

推荐答案

在这种情况下,可以安全地对Class<MyClass<?>>进行强制转换:

In this case it should be safe to do an unchecked cast to 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>之类的参数化类型的工厂本质上很尴尬.

This is a crufty solution, especially if you have many call sites like this, but there's no getting around the fact that class literals are parameterized with raw types, making their use as factories of parameterized types like MyClass<T> inherently awkward.

一个可能更干净的解决方案将使populateMap与类文字的使用脱钩:

A potentially cleaner solution would decouple populateMap from the use of class literals:

interface Parser<T> {

    T parse();
}

static void populateMap(Map<String, T> map, 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);

顺便说一句,我建议使用更灵活的签名(请参阅什么是PECS(生产者扩展了超级消费者) )?了解更多信息):

As an aside I recommend a more flexible signature (see What is PECS (Producer Extends Consumer Super)? for more info):

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

这篇关于Java泛型:如何为泛型类型化的类指定类类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆