Multiple annotations of the same type on one element?

Viewed 89167

I'm attempting to slap two or more annotations of the same type on a single element, in this case, a method. Here's the approximate code that I'm working with:

public class Dupe {
    public @interface Foo {
      String bar();
    }

    @Foo(bar="one")
    @Foo(bar="two")
    public void haha() {}
}

When compiling the above, javac complains about a duplicate annotation:

max@upsight:~/work/daybreak$ javac Dupe.java 
Dupe.java:5: duplicate annotation

Is it simply not possible to repeat annotations like this? Pedantically speaking, aren't the two instances of @Foo above different due to their contents being different?

If the above isn't possible, what are some potential workarounds?

UPDATE: I've been asked to describe my use case. Here goes.

I'm building a syntax sugarish mechanism to "map" POJOs to document stores such as MongoDB. I want to allow indexes to be specified as annotations on the getters or setters. Here's a contrived example:

public class Employee {
    private List<Project> projects;

    @Index(expr = "project.client_id")
    @Index(expr = "project.start_date")
    public List<Project> getProjects() { return projects; }
}

Obviously, I want to be able to quickly find instances of Employee by various properties of Project. I can either specify @Index twice with different expr() values, or take the approach specified in the accepted answer. Even though Hibernate does this and it's not considered a hack, I think it still makes sense to at least allow having multiple annotations of the same type on a single element.

8 Answers

combining the other answers into the simplest form ... an annotation with a simple list of values ...

@Foos({"one","two"})
private String awk;

//...

public @interface Foos{
    String[] value();
}

If you have only 1 parameter "bar" you can name it as "value". In this case you wont have to write the parameter name at all when you use it like this:

@Foos({@Foo("one"), @Foo("two")})
public void haha() {}

a bit shorter and neater, imho..

In the current version of Java, I was able to resolve this issue with the following annotation:

@Foo({"one", "two"})
Related