Instanciate类

时间:2017-03-21 10:40:47

标签: java generics reflection

我有一个班级

class Holder<SomeType extends AbstractType>{
    SomeType createType(){...}
}

然后在它之外,我打电话

Holder holder = new Holder<MyType>();

我无法弄清楚如何实现createType()方法。

我尝试了在StackOverflow和网络上找到的所有内容,但我总是在同一个死胡同中运行: 在运行时,如果我这样做

TypeVariable typeVariable = getClass().getTypeParameters()[0];
System.err.println("typeVariable "+typeVariable);

我得到了#34; SomeType&#34;而不是&#34; MyType&#34;,因此我无法获取相应的构造函数,因为我想使用Class.forName(&#34; MyType&#34;)而不是Class.forName(&#34) ; SomeType&#34;)导致java.lang.ClassNotFoundException

我使用SomeType扩展AbstractType,所以我知道我的所有MyTypes都有相同的构造函数。

我无法使用

ParameterizedType t = (ParameterizedType) MyClass.class.getGenericSuperclass();

因为Holder不是任何有用的子类

我可以在Holder类中做这样的事情,但是我正在寻找一种方法来使用反射,而不必在构造函数中传递参数

private final Class<SomeType> type;

public Holder(Class<SomeType> type) {
    this.type = type;
}

尝试我在网上看到的所有各种想法感觉就像是在追逐我的尾巴,所以我想我在这里错过了一个明显的元素。

感谢您的帮助!

编辑:我无法在Create instance of generic type in Java?中解决问题 我不能将该类作为createType(Class)的参数传递,因为在调用createType时我不会知道该类(当我无法调用时,此方法应该创建适当类型的子类)已知我的孩子应该是哪种类型)

1 个答案:

答案 0 :(得分:0)

就像托马斯在评论中所说,Java使用类型擦除。这意味着填充SomeType的具体类型不会隐式传递给Holder。但要实例化一个类,您需要该类型信息。因此,您必须将该信息明确传递给Holder。有几种方法可以做到这一点,其中一种是你找到的。在构建它时,Class对象传递给Holder

Java 8引入了方法引用,也允许您引用构造函数:

Function<String, MyType> cons = MyType::new;

这将创建一个功能接口Function的实例,其具有方法apply,该方法需要String并返回MyType

然后,您可以将此仿函数传递给Holder的构造函数,并保存以在createType中使用:

class Holder<SomeType extends AbstractType>{
    private final Function<String, SomeType> cons;

    public Holder(Function<String, SomeType> cons) {
        this.cons = cons;
        ...
    }

    SomeType createType() {
        return cons.apply("SomeString");
    }
}

这比使用Class以同样方式的优点是,您在编译时知道构造函数的签名,并且没有抛出异常。