Получить тип переменной в обработчике аннотаций

#java

Вопрос:

У меня есть процессор аннотаций. Я получаю список переменных класса, который был аннотирован моей аннотацией таким образом:

 @Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    for (TypeElement annotation : annotations) {
        Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(annotation);
        for (Element el : annotatedElements) {
            try {
                generate(el);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return true;
}

private void generate(Element annotatedElement) throws IOException {
        TypeElement targetClass = (TypeElement) annotatedElement;
        List<? extends Element> enclosedElements = targetClass.getEnclosedElements();
        List<VariableElement> fields = new ArrayList<>(enclosedElements.size());
        for (Element field : enclosedElements) {
            if (field.getKind() == ElementKind.FIELD amp;amp; !field.getModifiers().contains(Modifier.STATIC)) {
                fields.add((VariableElement) field);
            }
        }
       processFields(fields);
}
 

Теперь fields список содержит список всех переменных. Но мне нужно извлечь ТИП переменных, поэтому, например, если класс имеет
private String blabla я хочу получить String

Я делаю это следующим образом:

 void processFields(List<VariableElement> elements){
    List<String> types =elements
    .stream()
    .map( e -> e.asType().toString())
    .collect(Collectors.toList());        
}
 

Список types теперь содержит все типы переменных. Однако, если у меня будет такой класс, как этот

 @MyAnnotation
public class Test{
  @NotBlank(message = "message")
  private String name;
}
 

Тип переменной name не является строковым, ее
(@javax.validation.constraints.NotBlank(message="message") :: java.lang.String

Как я могу тогда просто печатать без аннотаций? Есть ли какой-нибудь способ?

Спасибо за помощь!

Ответ №1:

Добавьте элементы и переопределите init() , чтобы получить экземпляры элементов и типов.

 ...
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
...
    /** See {@link javax.annotation.processing.ProcessingEnvironment#getElementUtils()}. */
    protected Elements elements = null;
    /** See {@link javax.annotation.processing.ProcessingEnvironment#getTypeUtils()}. */
    protected Types types = null;
...
    @Override
    public void init(ProcessingEnvironment processingEnv) {
        elements = processingEnv.getElementUtils();
        types = processingEnv.getTypeUtils();
    }
...
 

К вашему сведению, вы можете упростить свой generate(Element) метод:

 ...
import javax.lang.model.util.ElementFilter;
...
private void generate(Element annotatedElement) throws IOException {
    List<VariableElement> fields =
        ElementFilter.fieldsIn(Collections.singleton(annotatedElement)).stream()
        .filter(t -> (! t.getModifiers().contains(Modifier.STATIC)))
        .collect(Collectors.toList());

    processFields(fields);
}
 

Ваш processFields(List<VariableElement>) метод может выглядеть примерно
так, как показано ниже. Я сделал все шаги явными, но вы можете посмотреть на
элемент типа
и
имя
методы для определения нужной строки.

 void processFields(List<VariableElement> in) {
    List<String> out =
        in.stream()
        .map(e -> e.asType())           /* javax.lang.model.type.TypeMirror */
        .map(e -> types.asElement(e))   /* javax.lang.model.element.Element */
        .map(e -> (TypeElement) e)      /* javax.lang.model.element.TypeElement */
        .map(e -> e.getQualifiedName()) /* javax.lang.model.element.Name */
        .map(e -> e.toString())
        .collect(Collectors.toList());
}