Java: получение внутреннего типа во вложенных параметризованных типах (отражение) - PullRequest
5 голосов
/ 16 февраля 2010

Большая часть документации, касающейся обработки стирания типов в Java, предполагает, что сценарий использования обрабатывает тип, подобный SomeType<ParamType>. Я пытаюсь обработать параметр метода для следующего метода:

public void setOtherReferenceRanges(List<ReferenceRange<T>> referenceRanges)

Когда экземпляр класса контейнера создается с типом DvQuantity, эта подпись должна стать public void setOtherReferenceRanges(List<ReferenceRange<DvQuanitity>> referenceRanges) во время выполнения.

Используя отражение, можно увидеть, что List имеет actualTypeArgument, равное ReferenceRange<T>. Поскольку рефлексия использует информацию о классе, я бы не ожидал, что она даст мне ReferenceRange<DvQuantity>. Однако когда я создал класс, содержащий этот метод, я передал тип DvQuantity как T. Таким образом, заполнение типа в T должно быть доступно для среды выполнения Java, но я не мог найти способ получить его. В итоге я получаю объект TypeVariableImpl, доступ к которому осуществляется с помощью отражения, который, похоже, не содержит никаких полезных данных.

Можете ли вы придумать какие-либо способы обнаружения этой информации во время выполнения?

Ответы [ 3 ]

1 голос
/ 16 февраля 2010

Когда вы говорите

когда я создал класс, содержащий этот метод

Полагаю, вы имеете в виду, когда создаете объект такого типа, например:

foo = new ContainerClass<DvQuantity>();

В этом случае из-за стирания невозможно восстановить тип DvQuantity.

Однако, если вы создаете класс , передавая параметр типа суперклассу, как это

class DvQuantityContainerClass extends ContainerClass<DvQuantity> {...}
...
foo = new DvQuantityContainerClass();

Или, короче, встроенный анонимный подкласс (который выглядит почти как первый пример, но с небольшим, но важным отличием):

foo = new ContainerClass<DvQuantity>(){};

Затем вы можете восстановить параметр типа, поскольку вы восстанавливаете параметр типа, используемый для расширения суперкласса во время выполнения. К сожалению, сама Java не предоставляет простого способа получить тип метода DvQuantityContainerClass.setOtherReferenceRanges с заполненным T. Для этого я написал gentyref , чтобы выполнить расширенное отражение универсальные типы:

Method m = DvQuantityContainerClass.class.getMethod("setOtherReferenceRanges", List.class);
// this will return List<ReferenceRange<DvQuanity>>, like you are lookingn for
return GenericTypeReflector.getExactParameterTypes(m, DvQuantityContainerClass.class)
0 голосов
/ 16 февраля 2010

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

Возможно, это не совсем правильно, но я думаю, что во время выполнения нет реального класса - просто объект без определенного типа, который соответствует интерфейсу T. Другими словами, стирание происходит не с объектами, но вместо этого с этими туманными (по крайней мере в мире ООП) типичными вещами.

http://java.sun.com/docs/books/tutorial/java/generics/erasure.html

Есть способы сбора информации о типах внутри самого класса (для T-типов потребуется метод getUnderlyingType () ... или что-то в этом роде), но это плохая идея. Если вам действительно нужен необработанный тип объекта, я бы пересмотрел использование обобщений.

0 голосов
/ 16 февраля 2010

Общая информация о типе стирается компилятором и недоступна во время выполнения. Когда мне нужно обеспечить определенный тип во время выполнения, я передаю аргумент класса:

public <T> void doSomething(T t, Class<T> c);

Это не всегда удобно или даже возможно, но во многих случаях это возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...