18

I`d like to create my own annotations to annotate some local variable. To write the annotation is not the problem, the problem is to get the information of them at the Runtime. I could only get some information from annotated methods or method parameters, but not from local variables. Is there any way to get it?

My own annotation is something like that:

public void m(int a)  
@MyOwnAnnotation(some information)  
int b = 5;  
}  

Or, as an alternative, is there any way to get the code of the method, to parse it further and finally get annotation value?

Thanks in advance.

Dmitry Sobetsky
  • 367
  • 1
  • 3
  • 13
  • your link in another comment gives you the answer: it's not supported by the class file format. I can give an answer with links to the JVM spec and explanation if you'd like, but I think that other question pretty much covers it. I am surprised that `apt` doesn't give you what you need. – parsifal Jun 21 '13 at 14:55

4 Answers4

21

With reflection you can't retrieve a local variable. So you can't retrieve an annotation on a local variable via reflection. I think that this kind of annotation is only used for compiler warnings.

You can look http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations.html

Local variable annotations are not retained in class files (or at runtime) regardless of the retention policy set on the annotation type. See JLS 9.6.1.2.

If you wan't to retrieve method code, you can use JavaParser (http://javaparser.org/).

try-catch-finally
  • 7,436
  • 6
  • 46
  • 67
PomPom
  • 1,468
  • 11
  • 20
14

As of Java 8, local variable annotations are retained in class files. As noted by Erick Hagstrom, this long-standing bug was fixed by JSR 308, which also added type annotations to the Java language.

However, Java's reflection API has not been updated to give access within method bodies. You will need to parse the classfile yourself. You can use a tool such as ASM. EDIT: I don't recommend JavaParser, because it has not been updated beyond Java 1.5. JavaParser has been updated.

mernst
  • 7,437
  • 30
  • 45
  • 2
    [JLS 9.6.4.2. @Retention](https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.4.2) says something different: _"[...] a Java compiler must ensure that `a` is represented in the binary representation of the class or interface in which `a` appears, unless `m` annotates a local variable declaration. An annotation on a local variable declaration is never retained in the binary representation."_ – Gerold Broser Mar 29 '17 at 18:21
5

JLS 9.6.1.2 does indeed state that local variable annotations are not retained. However, JSR 308 is working its way through the community process. It should give you the capability you need.

If you want an interim solution, here is an implementation of JSR 308.

mernst
  • 7,437
  • 30
  • 45
Erick G. Hagstrom
  • 4,873
  • 1
  • 24
  • 38
-4

At the moment, as mentioned in some other posts, you cannot retrieve a local variable value simply from the annotation alone.

However, I did have a simimlar issue and managed to come up with a solution using fields. Sample code is below:

Interface Class

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface test{
}

PoJo

public class testObject{
    @test
    private String one;
    private String two;

    //Getters and Setters
}

Get Object values

public void getFields (Object obj){
    Field fields = obj.getClass().getDeclaredFields();

    for (Field f : fields){
        test fieldAnnotation = f.getAnnotation(test.Class);
        if (fieldAnnotation != null){
            f.get(obj);
            // Do things here based on the values
        }
    }
}

Main Class

public static void main(String[] args){
    //Create object
    testObject test = new testObject();

    test.setOne("testOne");
    test.setTwo("testTwo");
    getFields(test);
}

Hopefully this helps in explaining how you can get the fields for an object based on the annotation. You are simply using the annotation to 'mark' the fields you want to retrieve and then reading the value from the object.

Amit Sinha
  • 68
  • 4