Как мне этого добиться?
public class GenericClass<T>
{
public Type getMyType()
{
//How do I return the type of T?
}
}
Все, что я пробовал до сих пор, всегда возвращает тип, Object
а не конкретный используемый тип.
java
generics
reflection
Гленн
источник
источник
Ответы:
Как уже упоминалось, это возможно только путем отражения в определенных обстоятельствах.
Если вам действительно нужен тип, это обычный (безопасный для типов) шаблон обхода:
источник
Foo foo1 = GetDao<Foo>(Foo.class).get(Foo.class, 1)
public static <T> GenericClass<T> of(Class<T> type) {...}
а затем назвать это такGenericClass<String> var = GenericClass.of(String.class)
. Немного приятнее.Я видел что-то подобное
в примере hibernate GenericDataAccessObjects
источник
class A implements Comparable<String>
, что фактическим параметром типа являетсяString
, но он НЕ МОЖЕТ сказатьSet<String> a = new TreeSet<String>()
, что фактическим параметром типа являетсяString
. Фактически, информация о параметре типа «стирается» после компиляции, как объяснено в других ответах.java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
за этот ответ.Class-Mate
от людей Джексона. Я написал здесь суть gist.github.com/yunspace/930d4d40a787a1f6a7d1(Class<T>) ((ParameterizedType)getClass().getSuperclass().getGenericSuperclass()).getActualTypeArguments()
чтобы получить фактические аргументы типа.Обобщения не овеществлены во время выполнения. Это означает, что информация отсутствует во время выполнения.
Добавление дженериков в Java с одновременной поддержкой обратной совместимости было непростой задачей (вы можете увидеть оригинальный документ об этом: сделать будущее безопасным для прошлого: добавить дженерики в язык программирования Java ).
По этому вопросу имеется обширная литература, и некоторые люди недовольны текущим состоянием, некоторые говорят, что на самом деле это приманка и в этом нет особой необходимости. Вы можете прочитать обе ссылки, я нашел их довольно интересными.
источник
Используйте гуаву.
Некоторое время назад, я отправил несколько примеров полноценных включая абстрактные классы и подклассы здесь .
Примечание: это требует , чтобы вы создать экземпляр подкласса из
GenericClass
так что он может правильно связать параметр типа. В противном случае он просто вернет тип какT
.источник
java.lang.IllegalArgumentException: class com.google.common.reflect.TypeToken isn't parameterized
. Поэтому я изменил строкуnew TypeToken(getClass()) { }
наnew TypeToken<T>(getClass()) { }
. Теперь код работает нормально, но Type по-прежнему 'T'. Смотрите это: gist.github.com/m-manu/9cda9d8f9d53bead2035default Type getParameterType() { final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {}; final Type type = typeToken.getType(); return type; }
GenericClass
, вы должны сделать этот класс,abstract
чтобы неправильное использование не компилировалось.Что вы можете.
Java не использует информацию во время выполнения по причинам обратной совместимости. Но информация фактически представлена в виде метаданных и может быть доступна через отражение (но она все еще не используется для проверки типов).
Из официального API:
http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29
Однако для вашего сценария я бы не использовал рефлексию. Я лично более склонен использовать это для кода платформы. В вашем случае я бы просто добавил тип в качестве параметра конструктора.
источник
Обобщение Java в основном выполняется во время компиляции, это означает, что информация о типе теряется во время выполнения.
будет скомпилировано в нечто вроде
Чтобы получить информацию о типе во время выполнения, вы должны добавить ее в качестве аргумента ctor.
Пример:
источник
private final Class<T> type;
Type t = //String[]
источник
Я использовал следующий подход:
источник
Я не думаю, что вы можете, Java использует стирание типов при компиляции, чтобы ваш код был совместим с приложениями и библиотеками, которые были созданы предварительными.
Из документов Oracle:
http://docs.oracle.com/javase/tutorial/java/generics/erasure.html
источник
Техника, описанная в этой статье Яном Робертсоном, работает для меня.
Короче быстрый и грязный пример:
источник
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Я думаю, что есть другое элегантное решение.
То, что вы хотите сделать, это (безопасно) «передать» тип параметра универсального типа из конкретного класса в суперкласс.
Если вы позволяете себе думать о типе класса как о «метаданных» в классе, это предлагает метод Java для кодирования метаданных во время выполнения: аннотации.
Сначала определите пользовательскую аннотацию вдоль этих линий:
Затем вы можете добавить аннотацию к вашему подклассу.
Затем вы можете использовать этот код, чтобы получить тип класса в вашем базовом классе:
Некоторые ограничения этого подхода:
PassedGenericType
) в ДВУХ местах, а не в не СУХОЙ.источник
Это мое решение:
источник
Вот рабочее решение !!!
ЗАМЕЧАНИЯ: Может использоваться только как суперкласс
1. Должен быть расширен с помощью typed class (
Child extends Generic<Integer>
)ИЛИ
2. Должен быть создан как анонимная реализация (
new Generic<Integer>() {};
).источник
Ты не можешь Если вы добавите в класс переменную-член типа T (вам даже не нужно ее инициализировать), вы можете использовать ее для восстановления типа.
источник
Вот один из способов, который мне пришлось использовать один или два раза:
Вместе с
источник
Одно простое решение для этой кабины, как показано ниже
источник
Чтобы завершить некоторые ответы здесь, мне нужно было получить ParametrizedType MyGenericClass, независимо от того, насколько высока иерархия, с помощью рекурсии:
источник
Вот мой трюк:
источник
T
переменная типа. В случае, еслиT
это переменная типа, varargs создает массив для удаленияT
. Смотрите, например, http://ideone.com/DIPNwd .В случае, если вы используете переменную store с использованием универсального типа, вы можете легко решить эту проблему, добавив метод getClassType следующим образом:
Позже я использую предоставленный объект класса, чтобы проверить, является ли он экземпляром данного класса, следующим образом:
источник
value
естьnull
? Во-вторых, что, еслиvalue
это подклассT
?Constant<Number> c = new Constant<Number>(new Integer(0)); Class<Number> n = c.getClassType();
возвращается,Integer.class
когда он должен вернутьсяNumber.class
. Вернее было бы вернутьсяClass<? extends T>
.Integer.class
это,Class<? extends Number>
но неClass<Number>
.Вот мое решение
Независимо от того, сколько уровней имеет ваша иерархия классов, это решение все еще работает, например:
В этом случае getMyType () = java.lang.String
источник
Exception in thread "main" java.lang.NullPointerException at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.<init>(Main.java:43) at Main.main(Main.java:61)
источник
Вот мое решение. Примеры должны объяснить это. Единственное требование заключается в том, что подкласс должен устанавливать общий тип, а не объект.
источник
Я сделал то же самое, что и @Moesio Above, но в Котлине это можно сделать так:
источник
Это может быть полезно для кого-то. Вы можете использовать java.lang.ref.WeakReference; сюда:
источник
WeakReference
? Пожалуйста, предоставьте некоторое объяснение с вашим ответом, а не просто код.SomeClass<MyClass>
вы можете создать экземплярSomeClass
и вызватьgetType
этот экземпляр и иметь время выполненияMyClass
.WeakReference
? То, что вы сказали, не отличается от большинства других ответов.AtomicReference
,List
,Set
).Я обнаружил, что это простое и понятное решение
источник
(T...t)
. (Вот почему этот код не работает.)