2015-01-04 2 views
-1

Там уже слишком много пост здесь предлагая делать:Создать экземпляр для общего T

class Foo<T>{ 
    Class<T> type; 
    public Foo(Class<T> type){ 
     this.type = type; 
    } 
    // then using newInstance method creating the instance 
} 

Проблема такого подхода заключается в том, что это не Java, который создает экземпляр, это разработчик, который вынужден pass в конструктор класса Foo. Итак, скажем, мне нужен конструктор без параметров, является ли Java все еще способным создать экземпляр?

Например, в C# мы получили активаторного типа, которые мы можем использовать так:

Object obj = Activator.CreateInstance<T>(); 

так, если у меня есть ниже класс в Java, и я не могу следовать за первое решение, что является альтернативой подход, который также аналогичен решению C#:

class Foo<T>(){ 
    public Foo(){ 
     if T is of Type X Then Do Y 
    } 
} 
+2

Ваш вопрос подсказывает, что вы уже знаете ответ. Дима прав. Из-за стирания типа в Java невозможно сделать что-либо в зависимости от типа 'T' во время выполнения. Единственный способ обойти это - передать объект класса «» в конструктор, но это несовместимо с наличием конструктора без параметров. Генераторы Java нигде не так сильны, как генераторы C#. Так оно и есть. –

+0

@pbabcdefp: Я думал, что создавать типы во время выполнения на C# тоже невозможно, но пару лет назад я почувствовал, что мне нужно это сделать, и я нашел решение (у меня есть проект на моем сайте), поэтому это означает, что там должен быть способом создания экземпляра T, подобного тому же на Java. Я не могу признать невозможным, как ответ, который я воспринимаю, поскольку мы еще не знаем ответа. – Ricky

+0

Возможный дубликат [Создать экземпляр родового типа в Java?] (Http://stackoverflow.com/questions/75175/create-instance-of-generic-type-in-java) – Radiodef

ответ

1

Нет, вы не можете этого сделать. Общие параметры - это только время компиляции, они полностью стираются и становятся недоступными во время выполнения. Также обратите внимание, что если вы делаете Activator.CreateInstance<Foo>() (если это было возможно) или Activator.CreateInstance(Foo.class), вы фактически передаете ту же самую точную информацию вашему методу CreateInstance, разница чисто синтаксическая.

+0

Не совсем Dima, мы не передаем ту же информацию, что и CreateInstance , не то же самое, что и CreateInstance (T args) – Ricky

+0

Да, это так и да (вы, наверное, по каким-то причинам поверили иначе, но пока вы не захотите на самом деле заявить об этом, это единственный ответ, который я могу вам дать). – Dima

+0

Фактически T представляет тип и в вашем примере на самом деле это должен быть Foo.GetType() (T не имеет метода GetType), поэтому мы используем typeof (Foo), поэтому, чтобы быть очень точным, общий CreateInstance не совсем такой же, как тот, который не является общим , но они не существуют на Java, поэтому я ищу решение. – Ricky

0

Возможно, если вы действительно необходимо сделать это.

Например, некоторые фреймворки внедрения зависимостей используют поля Instance<T> для разрешения и/или создания зависимостей во время выполнения.

Вы можете получить Class<T> объект с помощью классического вызова отражения:

Class<T> cls = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

Проверить этот ответ на фрагмент кода https://stackoverflow.com/a/3942033/2892277

Но (как упоминается также, что ответ), это не очень хорошая практика ,

+0

Я думаю, что это отражает тип класса, в котором он используется! – Ricky

+0

Он отражает 'Класс ' от 'Class >', который исходит из 'getClass()', если вызывается из 'SomeClass '. – Nikolay

0

Если разработчик создает подкласс Foo, вы можете восстановить T, используя что-то вроде TypeTools. Пример:

public class StringFoo extends Foo<String>{} 

Class<?> t = TypeResolver.resolveRawArgument(Foo.class, StringFoo.class); 
assert t == String.class; 

Если пользователь не подкласс Foo и просто конкретизирует его, значение T не могут быть восстановлены во время выполнения.