Multiple annotations of the same type on one element?

Solution 1:

Note: This answer is partially outdated since Java 8 introduced the @Repeatable annotation (see answer by @mernst). The need for a @Foos container annotation and dedicated handling still remain though.

Two or more annotations of same type aren't allowed. However, you could do something like this:

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

// pre Java 8
@Foos({@Foo(bar="one"), @Foo(bar="two")})
public void haha() {}

// post Java 8 with @Repeatable(Foos.class) on @Foo
@Foo(bar="one") @Foo(bar="two")
public void haha() {}

You'll need dedicated handling of Foos annotation in code though.

Solution 2:

Repeating annotations in Java 8

In Java 8 (released in March 2014), it is possible to write repeated/duplicate annotations.

See tutorial, Repeating Annotations.

See specification, JEP 120: Repeating Annotations.

Solution 3:

Apart from the other ways mentioned, there is one more less verbose way in Java8:

@Target(ElementType.TYPE)
@Repeatable(FooContainer.class)
@Retention(RetentionPolicy.RUNTIME)
@interface Foo {
    String value();

}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface FooContainer {
        Foo[] value();
        }

@Foo("1") @Foo("2") @Foo("3")
class Example{

}

Example by default gets, FooContainer as an Annotation

    Arrays.stream(Example.class.getDeclaredAnnotations()).forEach(System.out::println);
    System.out.println(Example.class.getAnnotation(FooContainer.class));

Both the above print:

@com.FooContainer(value=[@com.Foo(value=1), @com.Foo(value=2), @com.Foo(value=3)])

@com.FooContainer(value=[@com.Foo(value=1), @com.Foo(value=2), @com.Foo(value=3)])

Solution 4:

http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html

Starting from Java8 you can describe repeatable annotations:

@Repeatable(FooValues.class)
public @interface Foo {
    String bar();
}

public @interface FooValues {
    Foo[] value();
}

Note, value is required field for values list.

Now you can use annotations repeating them instead of filling the array:

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