Jér*_*nge 20 java enums annotations default-value
Java允许enum作为注释值的值.如何enum为enum注释值定义一种通用默认值?
我考虑过以下内容,但不会编译:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public <T extends Enum<T>> @interface MyAnnotation<T> {
T defaultValue();
}
Run Code Online (Sandbox Code Playgroud)
这个问题是否有解决方案?
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;
Run Code Online (Sandbox Code Playgroud)
当然,我们不能强制用户在编译时指定有效的默认值.但是,任何注释预处理都可以验证这一点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;
Run Code Online (Sandbox Code Playgroud)
注释处理器应在两个MyEnumAnnotation字段上搜索所提供的默认值.
这需要为每个枚举类型创建一个注释类型,但保证编译时检查类型安全.
如果你说如果在构造函数args中没有提供所述值,而不是在运行时关心泛型类型,那么当你说获得默认值时,你的意思并不完全清楚.
以下作品,但有点丑陋的黑客.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class Main {
@MyAnnotation(clazz = MyEnum.class, name = "A")
private MyEnum value;
public static v oid main(String[] args) {
new Main().printValue();
}
public void printValue() {
System.out.println(getValue());
}
public MyEnum getValue() {
if (value == null) {
value = getDefaultValue("value", MyEnum.class);
}
return value;
}
private <T extends Enum<?>> T getDefaultValue(String name, Class<T> clazz) {
try {
MyAnnotation annotation = Main.class.getDeclaredField(name)
.getAnnotation(MyAnnotation.class);
Method valueOf = clazz.getMethod("valueOf", String.class);
return clazz.cast(valueOf.invoke(this, annotation.value()));
} catch (SecurityException e) {
throw new IllegalStateException(e);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException(name, e);
} catch (IllegalAccessException e) {
throw new IllegalStateException(e);
} catch (NoSuchMethodException e) {
throw new IllegalStateException(e);
} catch (InvocationTargetException e) {
if (e.getCause() instanceof RuntimeException) {
throw (RuntimeException) e.getCause();
/* rethrow original runtime exception
* For instance, if value = "C" */
}
throw new IllegalStateException(e);
}
}
public enum MyEnum {
A, B;
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
Class<? extends Enum<?>> clazz();
String name();
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:我通过枚举的valueOf方法更改了getDefaultValue,因此如果给定的值不是枚举的引用实例,则会给出更好的错误消息.
我不确定你的用例是什么,所以我有两个答案:
答案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;
Run Code Online (Sandbox Code Playgroud)
当clazz是 时ImplicitType.class,使用字段类型作为枚举类。
答案2:
如果您想做一些框架魔法并希望维护编译器检查的类型安全性,您可以执行以下操作:
/** Marks annotation types that provide MyRelevantData */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface MyAnnotation {
}
Run Code Online (Sandbox Code Playgroud)
在客户端代码中,您将拥有
/** 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;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您将扫描该字段以查找再次用 进行注释的注释MyAnnotation。不过,您必须通过注释对象上的反射来访问该值。似乎这种方法在框架方面更复杂。
| 归档时间: |
|
| 查看次数: |
12399 次 |
| 最近记录: |