【问题标题】:How to new a class by name that defined in the field of type in generics class如何按在泛型类的类型字段中定义的名称新建一个类
【发布时间】:2011-10-26 22:53:41
【问题描述】:

我想使用 java 泛型来实现这样的功能:

public class Test<T> {
    public T data;

    public Test() {
        data = new T();
    }
}

但是java编译报错“Cannot instantiate the type T”,如何在java中实现这个功能?

【问题讨论】:

    标签: java generics


    【解决方案1】:

    你需要上课

    public Test(Class<? extends T> klass) {
        data = klass.newInstance();
    }
    

    【讨论】:

    • 请不要不必要地使用反射。
    • 这种“不必要的反思”如何?
    • ;) 因为class 是关键字
    • 是的,这个解决方案有效,但也有一些缺点:(1) 它假设类有一个零参数的构造函数。如果该类没有这样的构造函数,则会抛出运行时异常(编译器不会捕获它)。 (2) 它使用反射,比普通代码慢(你不应该经常使用反射)。
    • @krico 可以使用反射调用非默认构造函数。例如:T instance = klass.getConstructor(String.class, Integer.class).newInstance("myString", 42); 是的,我同意在大多数情况下使用反射造成的性能损失并不明显。但抛开性能不谈,使用反射时绕过了编译器,这意味着你必须格外小心,否则会出现运行时异常。
    【解决方案2】:

    对此的一种可能解决方案是提供SupplierT 的工厂。

    public class Test<T>{
         public T data;
    
         public Test(Supplier<T> supplier){
            data = supplier.get();
         }
    
         // or
    
         public Test(T t){
            data = t;
         }
    
    }
    

    【讨论】:

    • (对于“高级”用途(例如作为 API 的一部分发布),构造函数应为 public Test(Supplier&lt;? extends T&gt; supplier) {。如果您需要苹果供应商,麦金托什的供应商就可以了。
    【解决方案3】:

    这是不可能的,因为 Java 通过擦除实现泛型。

    有关更多详细信息,请参阅此类似问题的答案:

    【讨论】:

    • 有什么替代方法吗?
    • @user1010434:是的,您可以使用类似 kriko 的答案的模式,也可以只要求调用构造函数的代码直接为您提供 T
    • @user1010434 只需使用抽象工厂(就目前而言,无法知道T 是否具有可访问的无参数构造函数(C# 有一些额外的语法来指定所需的构造函数)。
    猜你喜欢
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多