简体   繁体   English

如何获取注释处理器中字段的类型?

[英]How to get the type of a field in an annotation processor?

I'm trying to write an annotation to check if an object is immutable at runtime.我正在尝试编写注释来检查对象在运行时是否不可变。 In order to do so, I check if the class of the object is final and then if all its attributes are also final.为此,我检查对象的类是否是最终的,然后检查它的所有属性是否也是最终的。 And then, I want to check the same thing recursively for the type of each field if it's not a primitive type.然后,如果每个字段不是原始类型,我想递归地检查相同的事情。

Here a piece of code:这里有一段代码:

for (Element subElement : element.getEnclosedElements()) {
    if (subElement.getKind().isField()) {
        isFinal=false;

        for(Modifier modifier : subElement.getModifiers()) {
            if (modifier.equals(Modifier.FINAL)) {
                isFinal=true;
                break;
            }
        }
        if (!isFinal) {
            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Field "+element+" is not immutable because it is not final");
        } else {
            // Here I want to restart my method recursively
        }
    }
}

How can I get my method to start all over again with the type of my field?我怎样才能让我的方法重新开始我的领域类型? How can I retrieve the type of the field, which is here a javax.lang.model.element.Element ?如何检索字段的类型,这里是javax.lang.model.element.Element

Edit: I need the type as declared in the containing class, which needs to be a final class to avoid any kind of mutability.编辑:我需要在包含类中声明的类型,它需要是最终类以避免任何类型的可变性。

I've been able to do it with Square's javapoet ClassName class:我已经能够使用Square 的 javapoet ClassName类来做到这一点:

Element element = ...
ClassName className = ClassName.get(element.asType());
String name = className.toString();

If, for example, the annotated field is a String , it will return Java.lang.String .例如,如果带注释的字段是String ,它将返回Java.lang.String I'm open to a better solution than this one.我愿意接受比这个更好的解决方案。

I think我认为

String type = element.asType().toString();

also gets the fully qualified name of the type of the fields.还获取字段类型的完全限定名称。

I never have needed javax.lang.model before.我以前从来不需要javax.lang.model If you intend to check things at runtime, I'd go through java.lang.Class and java.lang.reflect.Field instead.如果您打算在运行时检查内容,我会通过java.lang.Classjava.lang.reflect.Field来代替。 There you can use getType to obtain the type of the field.您可以在那里使用getType来获取字段的类型。 You can also have a look at all fields, including inherited ones, using getFields .您还可以使用getFields查看所有字段,包括继承的字段。 Or you can look at ancestor classes and their declared fields, to get at private ones as well.或者您可以查看祖先类及其声明的字段,以获取私有的。

Edit: the following consideration appears to be no longer relevant编辑:以下考虑似乎不再相关

Notice that even that type information will return the declared type, ie the type as it is written in the source code.请注意,即使是该类型信息也将返回声明的类型,即在源代码中写入的类型。 The field might still hold a reference to a derived class at runtime.该字段在运行时可能仍保留对派生类的引用。 Possible counter-measures would be having all those classes declared final , so that there can be no derived classes, or tracing all assignments to those fields, which would mean major static data flow analysis.可能的对策是将所有这些类都声明为final ,这样就不会有派生类,或者跟踪对这些字段的所有分配,这将意味着主要的静态数据流分析。 Not sure that's worth the effort.不确定这是否值得付出努力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM