Question

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?

Edit: I need the type as declared in the containing class, which needs to be a final class to avoid any kind of mutability.

Était-ce utile?

La solution

I've been able to do it with Square's javapoet ClassName class:

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. I'm open to a better solution than this one.

Autres conseils

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. If you intend to check things at runtime, I'd go through java.lang.Class and java.lang.reflect.Field instead. There you can use getTypeto obtain the type of the field. You can also have a look at all fields, including inherited ones, using 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, i.e. 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. Not sure that's worth the effort.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top