Хотя это правда, что Java сотрет типов в (таким образом, превращая List<String>
в List
), во многих случаях он фактически сохраняет общий тип во время выполнения, позволяя восстановить потерянную информацию для стирания. Вы можете получить фактические общие типы для них:
- Метод аргументы (ваш случай)
- возвращаемых типов Метода
- типов полей
- классов/интерфейсы
Это означает, что если у вас просто есть объект типа List, вы ничего не можете сделать, чтобы получить его общий тип (object.getClass()
доставит вам List
и все) - это было pe rmanually потерял. Но, если вы пытаетесь выяснить общий тип аргумента метода или любой из вышеперечисленных, вы обычно используете , используя. В вашем случае не включает в себя переменные типа или другие осложнения, это довольно просто, чтобы получить фактический тип:
ParameterizedType listArgument = (ParameterizedType) ClassDeclaringFoo.class.getMethod("foo", List.class).getGenericParameterTypes()[0];
Type listType = listArgument.getActualTypeArguments()[0]; //This will be a Class representing String, the type of the List
Если вы имели больше параметров и карту вместо:
public String foo(Object bar, Map<String, Number> possibleFoos) { ... }
код будет быть похожи:
ParameterizedType mapArgument = (ParameterizedType) ClassDeclaringFoo.class.getMethod("foo", Object.class, Map.class).getGenericParameterTypes()[1]; //1 is the index of the map argument
Type keyType = mapArgument.getActualTypeArguments()[0]; //This will be a Class representing String, the type of the Map key
Type valType = mapArgument.getActualTypeArguments()[1]; //This will be a Class representing Number, the type of the Map value
это с уверенностью предположить, что это то, что DWR использует так же, как типы аргументов метода.
Подобные методы доступны для других перечисленных случаев:
Class.getMethod(...).getGenericReturnType()
поможет вам реального типа возвращаемого
Class.getField(fieldName).getGenericType()
получит вам реальный тип поля
Class.getGenericSuperClass()
поможет вам реальные супер тип
Class.getGenericInterfaces()
предоставит вам реальные типы интерфейсов
Эквивалентные методы существуют разрешения доступа к AnnotatedType
(общий тип плюс аннотации на использование типа), введенный в Java 8:
Class.getMethod(...).getAnnotatedParameterTypes()
Class.getMethod(...).getAnnotatedReturnType()
Class.getField(fieldName).getAnnotatedType()
Class.getAnnotatedSuperClass()
Class.getAnnotatedInterfaces()
Теперь это все денди, когда ваш случай прост, как в примере. Но, представьте себе, если ваш пример выглядит следующим образом:
public T foo(List<T> possibleFoos) {...}
В этом случае getGenericParameterTypes()[0].getActualTypeArguments()[0]
даст вам T
что довольно бесполезно. Чтобы решить то, что стоит T
, вам нужно будет изучить определение класса и, возможно, суперклассы, при этом отслеживая, как переменные типа называются в каждом классе, поскольку имена могут быть разными в каждом.
Для того, чтобы работать с общим типом отражением проще, вы можете использовать прекрасную библиотека называется GenTyRef, что делает тяжелую работу за вас, и если вам нужна поддержка для AnnotatedType
с, вы можете использовать мою вилка называется GeAnTyRef (оба в Maven Центральный). Они также включают фабрику типов, которая позволяет создавать экземпляры (Annotated)Type
, которые вы не можете легко сделать с помощью обычного Java API. Существует также удобная реализация super type token, позволяющая получить литерал (Annotated)Type
.
С теми, что вы можете сделать все с общими типами, что Java позволяет без хлопот я объяснил выше:
GenericTypeReflector#getExactParameterTypes(...)
GenericTypeReflector#getExactReturnType(...)
GenericTypeReflector#getExactFieldType(...)
GenericTypeReflector#getExactSuperType(...)
И еще много операций, таких как figuri ng out, если один Type
является супертипом другого (аналогично Class#isAssignableFrom
, но для общих типов), разрешая переменные типа и т. д.
Благодарим вас за подробный ответ, именно это я и хотел знать! – Radim
Я использовал версию «hassle», и она отлично работает для списка, но она не работает для карты, потому что getParameterizedType возвращает объект класса.Поскольку у меня есть лучшее представление о вашем предыдущем посту, я попытался снова найти, как действовать с картой, но я ничего не нашел. Можете ли вы мне еще раз помочь? – Radim
@Radim Я обновил свой ответ, чтобы включить пример, в котором в качестве второго аргумента есть карта. Это то, что вам нужно? –
kaqqao