Вопрос-ответ

Create instance of generic type in Java?

Создать экземпляр универсального типа в Java?

Возможно ли создать экземпляр универсального типа в Java? Я думаю, основываясь на том, что я видел, что ответ таков no (из-за удаления типа), но мне было бы интересно, может ли кто-нибудь увидеть что-то, чего я не вижу:

class SomeContainer<E>
{
E createContents()
{
return what???
}
}

РЕДАКТИРОВАТЬ: Оказывается, для решения моей проблемы можно использовать токены супертипа, но для этого требуется много кода, основанного на отражении, как указано в некоторых ответах ниже.

Я оставлю этот вопрос открытым на некоторое время, чтобы посмотреть, придумает ли кто-нибудь что-нибудь кардинально отличающееся от статьи Artima Яна Робертсона.

Переведено автоматически
Ответ 1

Вы правы. Вы не можете этого сделать new E(). Но вы можете изменить это на

private static class SomeContainer<E> {
E createContents(Class<E> clazz) {
return clazz.newInstance();
}
}

Это мучительно. Но это работает. Обертывание его заводским шаблоном делает его немного более терпимым.

Ответ 2

В Java 8 вы можете использовать Supplier функциональный интерфейс для достижения этой цели довольно легко:

class SomeContainer<E> {
private Supplier<E> supplier;

SomeContainer(Supplier<E> supplier) {
this.supplier = supplier;
}

E createContents() {
return supplier.get();
}
}

Вы бы сконструировали этот класс следующим образом:

SomeContainer<String> stringContainer = new SomeContainer<>(String::new);

Синтаксис String::new в этой строке является ссылкой на конструктор.

Если ваш конструктор принимает аргументы, вы можете использовать вместо этого лямбда-выражение:

SomeContainer<BigInteger> bigIntegerContainer
= new SomeContainer<>(() -> new BigInteger(1));
Ответ 3

Я не знаю, помогает ли это, но когда вы создаете подкласс (в том числе анонимно) универсального типа, информация о типе доступна через отражение. например,

public abstract class Foo<E> {

public E instance;

public Foo() throws Exception {
instance = ((Class)((ParameterizedType)this.getClass().
getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
...
}

}

Итак, когда вы создаете подкласс Foo, вы получаете экземпляр Bar, например,

// notice that this in anonymous subclass of Foo
assert( new Foo<Bar>() {}.instance instanceof Bar );

Но это большая работа, и работает только для подклассов. Хотя может быть удобно.

Ответ 4

Вам понадобится какая-нибудь абстрактная фабрика того или иного типа, чтобы переложить ответственность на:

interface Factory<E> {
E create();
}

class SomeContainer<E> {
private final Factory<E> factory;
SomeContainer(Factory<E> factory) {
this.factory = factory;
}
E createContents() {
return factory.create();
}
}
java generics