Java允许将enum
作为注释值的值。如何为enum
批注值定义一种通用的默认enum
值?
我考虑过以下内容,但无法编译:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public <T extends Enum<T>> @interface MyAnnotation<T> {
T defaultValue();
}
是否有解决此问题的方法?
BOUNTY
对于这种Java极端情况,似乎没有直接解决方案。因此,我开始悬赏金以找到针对此问题的最优雅的解决方案。
理想的解决方案理想地应满足以下条件:
最佳解决方案
沙丘:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
// By not specifying default,
// we force the user to specify values
Class<? extends Enum<?>> enumClazz();
String defaultValue();
}
...
public enum MyEnumType {
A, B, D, Q;
}
...
// Usage
@MyAnnotation(enumClazz=MyEnumType.class, defaultValue="A");
private MyEnumType myEnumField;
当然,我们不能强制用户在编译时指定有效的默认值。但是,任何注释预处理都可以使用
valueOf()
进行验证。改进
Arian提供了一种优雅的解决方案来摆脱带注释字段中的
clazz
:@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
}
...
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@MyAnnotation()
public @interface MyEnumAnnotation {
MyEnumType value(); // no default has user define default value
}
...
@MyEnumAnnotation(MyEnum.FOO)
private MyEnumType myValue;
注释处理器应在字段中搜索两个
MyEnumAnnotation
以获得所提供的默认值。这需要为每个枚举类型创建一个注释类型,但要保证编译时检查类型的安全性。
最佳答案
我不确定您的用例是什么,所以我有两个答案:
答案1:
如果您只想编写尽可能少的代码,这是我的建议,扩展 Dunes的答案:
public enum ImplicitType {
DO_NOT_USE;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
Class<? extends Enum<?>> clazz() default ImplicitType.class;
String value();
}
@MyAnnotation("A");
private MyEnumType myEnumField;
当
clazz
为ImplicitType.class
时,将字段类型用作枚举类。答案2:
如果您想做一些框架魔术,并且想要维护编译器检查的类型安全,则可以执行以下操作:
/** Marks annotation types that provide MyRelevantData */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface MyAnnotation {
}
在客户端代码中,您将拥有
/** Provides MyRelevantData for TheFramework */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@MyAnnotation
public @interface MyEnumAnnotation {
MyEnumType value(); // default MyEnumType.FOO;
}
@MyEnumAnnotation(MyEnum.FOO)
private MyEnumType myValue;
在这种情况下,您将在字段中扫描以再次使用
MyAnnotation
进行注释的注释。但是,您将必须通过反射在注释对象上访问该值。在框架方面,这种方法似乎更复杂。