Создание объекта типа параметра

Я получил шаблонный класс следующим образом:

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

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

68 голосов | спросил Mercurious 18 22008vEurope/Moscow11bEurope/MoscowTue, 18 Nov 2008 23:20:05 +0300 2008, 23:20:05

5 ответов


0

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

}
ответил erickson 18 22008vEurope/Moscow11bEurope/MoscowTue, 18 Nov 2008 23:24:09 +0300 2008, 23:24:09
0

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

В Effective Java Джошуа Блох подробно рассматривает шаблон Builder и поддерживает общий интерфейс Builder:

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

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

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

ответил 20 42008vEurope/Moscow11bEurope/MoscowThu, 20 Nov 2008 01:05:01 +0300 2008, 01:05:01
0

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

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

class MyClass<T> 
{
    T field;
    public void myMethod(MyFactory<T> factory)
    {
       field = factory.newObject()
    }
}
ответил Dan Hodge 19 32008vEurope/Moscow11bEurope/MoscowWed, 19 Nov 2008 02:20:37 +0300 2008, 02:20:37
0

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

ответил krosenvold 18 22008vEurope/Moscow11bEurope/MoscowTue, 18 Nov 2008 23:50:18 +0300 2008, 23:50:18
0

Class classOfT

        try {
            t = classOfT.newInstance();//new T(); NOTE: type parameter T cannot be instantiated directly
        } catch (Exception e) {
            e.printStackTrace();
        }
ответил Kevendra 18 62017vEurope/Moscow11bEurope/MoscowSat, 18 Nov 2017 13:22:12 +0300 2017, 13:22:12

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132