При компиляции универсальных типов (в частности, списков(List)) в Java, как известно, информация о параметре типа (<T>) удаляется, и в рантайме получить эту информацию нельзя. Но, как говорится, если нельзя но очень хочется... :)
Сразу оговорюсь, с полями и переменными, действительно сделать ничего нельзя и определить параметр типа, который содержится внутри не получится (в смысле, что я на данный момент такого способа не знаю). А вот с параметрами метода очень даже можно !
Итак...
Задача 1
Дано :
Объект класса с методом void setMyList(List<String> param){}
Требуется :
во время выполнения, определить тип, содержащийся в списке List параметра param
Решение :
public static Class getClassName(Method method)
Class clazz;
Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
// генерик
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
Class = (Class) pt.getActualTypeArguments()[0];
}
// обычный тип (не генерик)
if (type instanceof Class) {
clazz = (Class) type;
}
}
return clazz;
}
Как получить Method класса, я здесь останавливаться не буду, это можно почитать в статьях про reflection API.
Усложним ситуацию, и предположим, что мы инстанцировали объект, с помощью springframework, и по каким-то причинам
этот объект инстанцирован не явно, а через оболочку-прокси, с использованием CGLIB. Примером может служить создание объектов в контексте безопасности spring-security. Вобщем суть в том, что вместо объекта нашего собственного класса, мы работаем с объектом класса-прокси, и в описании метода (того самого Method) у него уже нет информации о типе генерика. Но, вода дырочку найдёт...
Задача 2
Дано :
Объект класса, инстанцированного через spring, с включённым контекстом безопасности, с методом void setMyList(List<String> param){}
Требуется :
во время выполнения, определить тип, содержащийся в списке List параметра param
Решение :
public static Class getClassNameCGILIB(Method method) {
Class clazz;
if (!AopUtils.isCglibProxyClass(method.getDeclaringClass())) {
Class baseClass = method.getDeclaringClass().getSuperclass(); // исходный класс, для которого сделана заглушка
try {
Method baseMethod = baseClass.getMethod(method.getName(), method.getParameterTypes());
clazz = getClassName(baseMethod);
} catch (NoSuchMethodException e) {
e.printStackTrace(); //TODO сделать обработку ошибок
}
}
}
P.S.: Описанные методы точно работают на Sun JDK 1.6.
Сразу оговорюсь, с полями и переменными, действительно сделать ничего нельзя и определить параметр типа, который содержится внутри не получится (в смысле, что я на данный момент такого способа не знаю). А вот с параметрами метода очень даже можно !
Итак...
Задача 1
Дано :
Объект класса с методом void setMyList(List<String> param){}
Требуется :
во время выполнения, определить тип, содержащийся в списке List параметра param
Решение :
public static Class getClassName(Method method)
Class clazz;
Type[] types = method.getGenericParameterTypes();
for (Type type : types) {
// генерик
if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
Class = (Class) pt.getActualTypeArguments()[0];
}
// обычный тип (не генерик)
if (type instanceof Class) {
clazz = (Class) type;
}
}
return clazz;
}
Как получить Method класса, я здесь останавливаться не буду, это можно почитать в статьях про reflection API.
Усложним ситуацию, и предположим, что мы инстанцировали объект, с помощью springframework, и по каким-то причинам
этот объект инстанцирован не явно, а через оболочку-прокси, с использованием CGLIB. Примером может служить создание объектов в контексте безопасности spring-security. Вобщем суть в том, что вместо объекта нашего собственного класса, мы работаем с объектом класса-прокси, и в описании метода (того самого Method) у него уже нет информации о типе генерика. Но, вода дырочку найдёт...
Задача 2
Дано :
Объект класса, инстанцированного через spring, с включённым контекстом безопасности, с методом void setMyList(List<String> param){}
Требуется :
во время выполнения, определить тип, содержащийся в списке List параметра param
Решение :
public static Class getClassNameCGILIB(Method method) {
Class clazz;
if (!AopUtils.isCglibProxyClass(method.getDeclaringClass())) {
Class baseClass = method.getDeclaringClass().getSuperclass(); // исходный класс, для которого сделана заглушка
try {
Method baseMethod = baseClass.getMethod(method.getName(), method.getParameterTypes());
clazz = getClassName(baseMethod);
} catch (NoSuchMethodException e) {
e.printStackTrace(); //TODO сделать обработку ошибок
}
}
}
P.S.: Описанные методы точно работают на Sun JDK 1.6.
Комментариев нет:
Отправить комментарий