我试图在一个元素上拍两个或多个相同类型的注释,在本例中是一个方法.这是我正在使用的近似代码:
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: duplicate annotation
是不是可以重复这样的注释?从小学的角度讲,由于内容不同,@Foo的两个实例不同吗?
如果无法实现上述目标,那么有哪些潜在的解决方法?
更新:我被要求描述我的用例.开始.
我正在构建一种语法加糖机制,将POJO"映射"到文档存储,例如MongoDB.我想允许索引在getter或setter上指定为注释.这是一个人为的例子:
public class Employee { private Listprojects; @Index(expr = "project.client_id") @Index(expr = "project.start_date") public List getProjects() { return projects; } }
显然,我希望能够通过Project的各种属性快速查找Employee的实例.我可以使用不同的expr()值指定@Index两次,或者采用接受的答案中指定的方法.即使Hibernate这样做并且它不被认为是黑客,我认为至少允许在单个元素上具有相同类型的多个注释仍然是有意义的.
不允许两个或多个相同类型的注释.但是,你可以这样做:
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.
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)])
正如sfussenegger所说,这是不可能的.
通常的解决方案是构建一个"多个"注释,它处理前一个注释的数组.它的名称通常相同,后缀为's'.
顺便说一句,这在大型公共项目(例如Hibernate)中非常常用,所以它不应该被视为黑客攻击,而是一种正确的解决方案.
根据您的需要,最好允许您的早期注释处理多个值.
例:
public @interface Foo { String[] bars(); }