Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

annotation invisible?

This puzzles me. I have a class with a custom annotation and I can't seem to verify that the annotation is present. What am I doing wrong here? If I run MyOperationTest (see below), I get this as a result:

implements Library.Operation: true
has @Library.Marker: false
Tada!

Library.java:

package com.example.gotchas;

public class Library {
    private Library() {}

    public @interface Marker {}

    public interface Operation {
        public void execute(); 
    }
}

MyOperation.java:

package com.example.gotchas;

@Library.Marker
public class MyOperation implements Library.Operation {
    @Override public void execute() {
        System.out.println("Tada!");
    }
}

MyOperationTest.java:

package com.example.gotchas;

public class MyOperationTest {
    static public void main(String[] args)
    {
        try {
            Class<?> cl = Class.forName("com.example.gotchas.MyOperation");
            boolean implementsLibraryOperation =
                Library.Operation.class.isAssignableFrom(cl);
            boolean hasLibraryMarker =
                cl.isAnnotationPresent(Library.Marker.class);
            System.out.println("implements Library.Operation: "
                    +implementsLibraryOperation);
            System.out.println("has @Library.Marker: "+hasLibraryMarker);
            if (implementsLibraryOperation)
            {
                Class<? extends Library.Operation> opClass = 
                    cl.asSubclass(Library.Operation.class); 
                Library.Operation op = opClass.newInstance();
                op.execute();
            }
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        catch (InstantiationException e) {
            e.printStackTrace();
        }
        catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
like image 517
Jason S Avatar asked Sep 10 '10 21:09

Jason S


2 Answers

You have to define @Retention for your annotation:

@Retention(RetentionPolicy.RUNTIME)
public @interface Marker {}

Otherwise the annotation is not retained at runtime.

(You can also add explicit @Target(ElementType.TYPE) if you want to limit the usage of your annotation only on classes)

As a sidenote - it is not a common practice to define annotations as inner classes.

like image 121
Bozho Avatar answered Oct 21 '22 01:10

Bozho


By default, annotation retention policy is CLASS, which does not make your annotation available to reflection. You should qualify it when declaring the annotation.

like image 37
Marat Salikhov Avatar answered Oct 21 '22 02:10

Marat Salikhov