#java #annotations #annotation-processing
#java #примечания #обработка аннотаций
Вопрос:
Я пишу процессор аннотаций, которому необходимо сгенерировать код, вызывающий статический метод, такой как Collectors.toList()
(полная подпись: public static <I> Collector<I, ?, List<I>> toList()
)
Пример ввода:
class Pojo<X> {
public @CollectWith("Collectors.toList()") List<Thing<X>> things;
}
Фрагмент кода, сгенерированный выше:
Collector<Thing<X>, ?, List<Thing<X>>> thingsCollector = Collectors.toList();
- Базовый возвращаемый тип вызова метода всегда
Collector<T,A,R>
- Из контекста вызова код знает
R
(выше этоList<Thing<X>>
) - Переменные типа
T
иA
(иI
) неизвестны
Части головоломки
// Lookup specified Collector method
TypeElement collectors = elements.getTypeElement("java.util.stream.Collectors");
ExecutableElement toListMethod = findMethod(collectors, "toList");
DeclaredType toListMethodReturnType = (DeclaredType)toListMethod.getReturnType(); // java.util.stream.Collector<T,?,java.util.List<T>>
// R is already known.
DeclaredType R = ... // java.util.List<Thing<X>>
Вопрос: Существует ли какой-либо код, который разрешает отсутствующие переменные типа и может вычислить DeclaredType
из thingsCollector
, чтобы быть Collector<Thing<X>, ?, List<Thing<X>>>
.
Комментарии:
1. Я не понимаю, что вы пытаетесь получить, где у вас сбой? Не могли бы вы, пожалуйста, объяснить
2. Учитывая, что мы знаем R, как нам определить I (или <T, A, R>)
3. Что вы имеете в виду
R
? Я вижуr
в вашем APT-коде, ноreturnType
этоjava.util.stream.Collector<T,?,java.util.List<T>>
согласно комментарию — вы хотитеT
? илиList<T>
в данном случае? Но чтобы добраться доList<Thing<X>>
, вам нужно было бы специализироваться, указав, чтоT
такое (Things<X>
), а затем прочитать последний параметр типа?4. Проверьте эту библиотеку . Не уверен, какими функциями он обладает, но это единственное, с чем я когда-либо сталкивался, что звучит уместно. Если я не ошибаюсь, библиотека, которая работает с
java.lang.reflect.Type
(т. Е. загруженными типами), была бы бесполезна, поскольку процессоры аннотаций работают только сjavax.lang.model.type
(которые, как я понимаю, являются только дескрипторами типов, а не фактическими загруженными типами), верно? Я думаю, что связанная библиотека предоставляет impl на основе отражения, что может позволить вам использовать библиотеки отражения обычного типа, такие как GenTyRef , но сейчас я просто предполагаю.5. Если разобраться в этом немного подробнее, то у него есть
ReflectionTypes#resolveActualTypeArguments
который, кажется, делает именно то, что вам нужно. Не могу преобразовать это в правильный ответ, поскольку сейчас у меня нет компьютера, поэтому я публикую только комментарии. Кстати, связанная с Java проблема была закрыта как поставленная в JDK8, что означает, что это уже на Java, я думаю, нет необходимости во внешней библиотеке.