如何通过.class获得泛型类型?

时间:2014-12-06 20:41:56

标签: java generics type-erasure type-safety raw-types

有问题的代码如下所示。

class GenericClass<T> {
    // ...
}

class RegisterHandler<T> {
    // ...
    public void register( Class<T> klazz ) {
        // do something
    }
    // ...
}

class GenericClassRegisterHandler extends RegisterHandler<GenericClass<?>> {
    // ...
}

public static void registerAll() {
    // ...
    new GenericClassRegisterHandler().register( GenericClass.class );
    // error: actual argument Class<GenericClass> cannot be converted to Class<GenericClass<?>> by method invocation conversion
    // ...
}

唯一的方法是使用rawtypes,方法是将register改为Class klazz而不是Class<T>,或者将new GenericClassRegisterHandler()转换为(RegisterHandler)new GenericClassRegisterHandler()。由于这两个“修复”都利用了原型并且我不想使用它们(我为什么要这样做?我应该能够Class<GenericClass<?>>以某种方式得到.class!),但我看不到其他解决方案至今。我是否遗漏了一些显而易见的东西,而且可能没有重新包装等等,或者它只是不可能?

注意:Wrapping a Class<?> type generics error是一个很好的&amp;启发查找,但在这里不起作用。

注2:虽然EJ 2nd中的Bloch正在讨论类似问题,但我无法找到任何明确的解决方案。

由于(Class<GenericClass<?>>) GenericClass.class

,显而易见的incompatible types: Class<GenericClass<?>> cannot be converted to Class<GenericClass>无效

http://ideone.com/Fr4yng

上的测试代码段

3 个答案:

答案 0 :(得分:1)

这项任务可以通过小修改来解决:

static class RegisterHandler<T> {
    public <E extends T> void register( Class<E> klazz ) { // <== Note additional generics customization.
        // do something
    }
}

同意,泛型有点棘手=)

答案 1 :(得分:0)

我的解决方案是进行双重演员。

 new GenericClassRegisterHandler()
    .register( (Class<GenericClass<?>>) (Class<?>) GenericClass.class );

虽然它可能不是最优雅的,但在某些情况下(例如,您是制作人,消费者的界面是一成不变的,或者您只是不喜欢想要因任何其他原因而改变它)它是最好的 - 因为它是唯一可能的。

答案 2 :(得分:-1)

怎么样

class GenericClassRegisterHandler extends RegisterHandler<GenericClass>

我知道,你说,你不想使用“原始”类型,但GenericClass<?>不再是“原始”,而是GenericClass用于所有意图和目的。