一个元素上有多个相同types的注释?

我试图在单个元素上打两个或多个相同types的注释,在这种情况下是一个方法。 以下是我正在使用的近似代码:

public class Dupe { public @interface Foo { String bar(); } @Foo(bar="one") @Foo(bar="two") public void haha() {} } 

编译上面的代码时,javac会抱怨重复的注释:

 max @ upsight:〜/ work / daybreak $ javac Dupe.java 
 Dupe.java:5:重复注释

难道不可能重复这样的注释吗? 迂回地说,@Foo的两个实例不是因为内容不同而有所不同吗?

如果以上是不可能的,有什么潜在的解决方法?

更新:我被要求描述我的用例。 开始。

我正在构build一个语法糖食机制来将POJO“映射”到像MongoDB这样的文档商店。 我想允许索引被指定为getters或setters的注释。 这是一个人为的例子:

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

显然,我希望能够通过Project的各种属性快速find员工的实例。 我可以用不同的expr()值指定@Index两次,也可以采用接受的答案中指定的方法。 即使Hibernate做到这一点,它不被认为是一个黑客攻击,我认为它仍然是有意义的,至less允许在一个单一的元素有多个相同types的注释。

两个或更多相同types的注释是不允许的。 不过,你可以这样做:

 public @interface Foos { Foo[] value(); } @Foos({@Foo(bar="one"), @Foo(bar="two")}) public void haha() {} 

您需要在代码中专门处理Foos注释。

顺便说一句,我刚刚使用这个2小时前解决同样的问题:)

在Java 8(2014年3月发布)中,可以编写重复/重复的注释。 请参阅http://docs.oracle.com/javase/tutorial/java/annotations/repeating.html

正如sfussenegger所说,这是不可能的。

通常的解决scheme是构build一个“多重”注释 ,处理以前注释的数组。 它通常被命名为相同的,带有's'后缀。

顺便说一句,这在大型公共项目(例如Hibernate)中非常有用,所以不应该被认为是黑客,而是一个正确的解决scheme。


根据您的需要,最好允许您之前的注释处理多个值

例:

  public @interface Foo { String[] bars(); } 

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

从Java8开始,您可以描述可重复的注释:

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

请注意,值列表中的value是必填字段。

现在,您可以使用重复它们而不是填充数组的注释:

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

除了上面提到的其他方法之外,在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{ } 

默认情况下,示例将FooContainer作为注释

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

上面的打印:

@ 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)])

如果你只有一个参数“bar”,你可以把它命名为“value”。 在这种情况下,当你像这样使用它时,你不必写参数名称:

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

有点短,整洁,恕我直言..

将其他答案组合成最简单的forms…一个简单的值列表的注释…

 @Foos({"one","two"}) private String awk; //... public @interface Foos{ String[] value(); }