将参数化的Class实例传递给构造函数

时间:2014-03-03 17:14:53

标签: java generics

我迷失在仿制药的丛林中,请帮助我:)我有这样的事情:

public class BaseClass<TYPE> {
    public BaseClass(Class<TYPE> clazz) {};
}

public class FirstLevelClass<REFRESHABLE 
    extends RefreshableInterface> extends BaseClass<REFRESHABLE> {

    public FirstLevelClass(Class<REFRESHABLE> clazz) {
        super(clazz);
    };
}

public class Argument<T extends AnyOtherClass> 
    implements RefreshableInterface {

    public refresh() {}
}

pulbic class ProblematicClass 
    extends FirstLevelClass<Argument<AnyOtherClassDescendant>> {

    public ProblematicClass() {
        //Compiler error: Constructor 
        //FirstLevelClass<Argument<AnyOtherClassDescendant>>(Class<Argument>) is undefined
        super(Argument.class); 
    }
}

据我所知,编译器应该接受Argument,因为它实现了RefreshableInterface

  • 为什么会出现此错误?
  • 如何让ProblematicClass正常工作?

ps:如果你有更好的头衔,请改变它。我无法弥补。

1 个答案:

答案 0 :(得分:10)

问题是,您的构造函数需要Class<T>,并且代码中的T被推断为Argument<AnyOtherClassDescendant>

因此,您应该传递Class<Argument<AnyOtherClassDescendant>>,然后传递Class<Argument>。但是您无法直接传递Class实例,因为您无法Argument<AnyOtherClassDescendant>.class

但是,您可以通过将类类型转换为必需的实例来解决问题:

public ProblematicClass() {
    super((Class<Argument<AnyOtherClassDescendant>>)(Class<?>)Argument.class); 
}

注意,您要先将Class<Argument>首先Class<?>转换为Class<Argument<AnyOtherClassDescendant>>,然后将结果类型转换为Class。没有简单的方法可以实现这一目标。

这背后的原因是,泛型类型的所有参数化实例化只有一个true实例,它与类本身相关联。泛型类型的单个编译单元,仅编译为单个类文件。我想这与C ++实现模板的方式不同。在那里,您可以获得不同的机器代码以进行不同的实例化。

因此,如果您执行以下代码,您将获得List<String> strList = new ArrayList<String>(); List<Integer> intList = new ArrayList<Integer>(); boolean isSameClassInstance = strList.getClass() == intList.getClass(); System.out.println(isSameClassInstance); 作为输出:

{{1}}