Создание экземпляра объекта типа parameter

У меня есть класс-шаблон, следующим образом:

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

Как создать новый экземпляр T в моем классе?

5 ответов


после стирания типа, все, что известно о 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();
  }

}

другой не отражающий подход-использовать гибридный конструктор / абстрактный Заводской шаблон.

в эффективной Java Джошуа блох подробно описывает шаблон Builder и выступает за общий интерфейс Builder:

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

конкретные строители могут реализовать этот интерфейс, а внешние классы могут использовать конкретный Строитель для настройки строителя по мере необходимости. Строитель может быть передан MyClass как Builder<T>.

используя этот шаблон, вы можете сделать новые экземпляры T, даже если T параметры конструктора или требует дополнительной настройки. Конечно, вам понадобится какой-то способ передать строителя в MyClass. Если вы ничего не можете передать в MyClass, то Builder и Abstract Factory отсутствуют.


Это может быть более тяжелый вес, чем то, что вы ищете, но он также будет работать. Обратите внимание, что если вы примете этот подход, было бы разумнее вводить фабрику в MyClass при ее построении вместо передачи ее в ваш метод каждый раз, когда он вызывается.

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

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

Если вы готовы к подклассу, вы также можете избежать стирания, проверьте http://www.artima.com/weblogs/viewpost.jsp?thread=208860


класс classOfT

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