类型参数的实例化对象


88

我有一个模板类,如下所示:

class MyClass<T>
{
    T field;
    public void myMethod()
    {
       field = new T(); // gives compiler error
    }
}

如何在课堂上创建T的新实例?

Answers:


85

在类型擦除之后,只知道T它是的某个子类Object。您需要指定一些工厂来创建的实例T

一种方法可以使用Supplier<T>

class MyClass<T> {

  private final Supplier<? extends T> ctor;

  private T field;

  MyClass(Supplier<? extends T> ctor) {
    this.ctor = Objects.requireNonNull(ctor);
  }

  public void myMethod() {
    field = ctor.get();
  }

}

用法可能如下所示:

MyClass<StringBuilder> it = new MyClass<>(StringBuilder::new);

或者,您可以提供一个Class<T>对象,然后使用反射。

class MyClass<T> {

  private final Constructor<? extends T> ctor;

  private T field;

  MyClass(Class<? extends T> impl) throws NoSuchMethodException {
    this.ctor = impl.getConstructor();
  }

  public void myMethod() throws Exception {
    field = ctor.newInstance();
  }

}

Supplier位于哪个包中?MyClass(Class <?extends T> impl)必须声明throws NoSuchMethodException要编译。您的答案很不幸对Java初学者不友好。
purucat

@ user927387java.util.function.Supplier
埃里克森

Supplier <T>需要Java 8,JFTR才有价值。
Fran Marzoa

14

另一种非反射方法是使用混合的Builder / Abstract Factory模式。

在Effective Java中,Joshua Bloch详细介绍了Builder模式,并提倡通用的Builder接口:

public interface Builder<T> {
  public T build();
}

具体的构建器可以实现此接口,外部类可以根据需要使用具体的构建器来配置构建器。该构建器可以作为传递给MyClass Builder<T>

使用此模式,T即使T具有构造函数参数或需要其他配置,也可以获取的新实例。当然,您需要某种方式将Builder传递给MyClass。如果您不能将任何东西传递给MyClass,那么Builder和Abstract Factory就会退出。


12

这可能比您要查找的要重,但它也可以使用。请注意,如果采用这种方法,则将工厂构造时将工厂注入MyClass而不是每次调用时都将其传递到您的方法中会更有意义。

interface MyFactory<T> 
{
    T newObject();
}

class MyClass<T> 
{
    T field;
    public void myMethod(MyFactory<T> factory)
    {
       field = factory.newObject()
    }
}

1
良好的,非反省的方法;反思并非总是一种选择。myMethod应该能够接受MyFactory <?延伸T>,对不对?
erickson

1
打个好电话-您需要在工厂上放置一个有界通配符,以允许在myMethod()中创建T类型的对象和T的子类。
丹·霍奇


-3

类classOfT

        try {
            t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
        } catch (Exception e) {
            e.printStackTrace();
        }

2
该classOfT类在哪里声明?
Fran Marzoa
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.