简体   繁体   English

返回具有泛型类型的Class实例

[英]Return a Class instance with its generic type

Here's a simple example that demonstrates a type-erasure-related issue I am running into. 这是一个简单的示例,演示了我遇到的与类型擦除相关的问题。 I have a class like this: 我有一个这样的课:

public abstract class AbstractHandler<T> {

    ...
    public abstract Class<T> handledType();
}

Then I have this implementation: 然后我有这个实现:

public class ConcreteHandler extends AbstractHandler<Map<String, List<Thing>>> {

    @Override
    public Class<Map<String, List<Thing>>> handledType() {
        //what do I return here?!
    }
}

I can't return Map<String, List<Thing>>.class , since that's not even valid syntactically. 我不能返回Map<String, List<Thing>>.class ,因为它甚至不能在语法上有效。 I tried making the generic type-parameter in the subtype to be HashMap<String, List<Thing>> and then returning new HashMap<String, List<Thing>>().getClass() , but that doesn't work because the return type of Class<T>#getClass() is Class<? extends T> 我尝试将子类型中的泛型类型参数设置为HashMap<String, List<Thing>>然后返回new HashMap<String, List<Thing>>().getClass() ,但这不起作用,因为返回类型Class<T>#getClass()Class<? extends T> Class<? extends T> . Class<? extends T> I looked at TypeToken from Guava, and the getRawType method seemed promising, but it returns Class<? super T> 我从Guava看了TypeTokengetRawType方法看起来很有希望,但它返回Class<? super T> Class<? super T> . Class<? super T>

I have a workaround for the time being that looks like this: 我现在有一个解决方法,看起来像这样:

public class ThingListMap {
    private Map<String, List<Thing>> thingListMap;

    ...
}

and I just use ThingListMap as the generic type-parameter. 我只是使用ThingListMap作为泛型类型参数。

Another possible workaround is to perform a forced cast: 另一种可能的解决方法是执行强制转换:

public Class<Map<String, List<Thing>>> handledType() {
    return (Class<Map<String, List<Thing>>>) new HashMap<String, List<Thing>>().getClass();
}

Is there a more-elegant way to do this? 有更优雅的方式吗?

EDIT: In response to one of the answers, I cannot change the signature of the handledType method since I do not own or control its source. 编辑:响应其中一个答案,我无法更改handledType方法的签名,因为我不拥有或控制其来源。

For some reason, Java doesn't allow you to cast Map.class directly to Class<Map<String, List<Thing>>> . 出于某种原因,Java不允许您将Map.class直接转换为Class<Map<String, List<Thing>>> It's an unchecked cast anyway. 无论如何,这是一个未经检查的演员。

But it's legal to cast it twice, first to Class<?> , then to Class<Map<String, List<Thing>>> . 但是将它强制转换两次是合法的,首先是Class<?> ,然后是Class<Map<String, List<Thing>>>

return (Class<Map<String, List<Thing>>>) (Class<?>) Map.class;

Being an unchecked cast, you may want to add @SuppressWarnings("unchecked") . 作为未经检查的演员,您可能想要添加@SuppressWarnings("unchecked")

Guava's approach to this is to use TypeToken s. Guava的方法是使用TypeToken Your class would become 你的课将成为

public abstract class AbstractHandler<T> {
    public TypeToken<T> handledType();
}

public class ConcreteHandler extends AbstractHandler<Map<String, List<Thing>>> {
    @Override
    public TypeToken<Map<String, List<Thing>>> handledType() {
        return new TypeToken<Map<String, List<Thing>>>() {};
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM