Я отримав клас шаблону таким чином:
class MyClass<T>
{
T field;
public void myMethod()
{
field = new T(); // gives compiler error
}
}
Як створити новий екземпляр T у своєму класі?
Відповіді:
Після стирання типу відомо 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.util.function.Supplier
Іншим невідбиваючим підходом є використання гібридного шаблону 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 вийшли.
Це може бути більш важкою вагою, ніж те, що ви шукаєте, але це також буде працювати. Зверніть увагу, що якщо ви застосуєте такий підхід, було б більш розумно вводити завод у 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();
}
Supplierвін знаходиться? `MyClass (Class <? Extends T> impl)` повинен оголосити `викидає NoSuchMethodException` для компіляції. На жаль, ваша відповідь не є доброзичливою для початківців Java.