gpt4 book ai didi

java - Java枚举注解值的枚举默认值

转载 作者:IT老高 更新时间:2023-10-28 20:53:42 30 4
gpt4 key购买 nike

Java 允许 enum 作为注释值的值。如何为 enum 注释值定义一种通用的默认 enum 值?

我已经考虑了以下,但它不会编译:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public <T extends Enum<T>> @interface MyAnnotation<T> {

T defaultValue();

}

这个问题有没有解决办法?

赏金

似乎没有针对这种 Java 极端情况的直接解决方案。所以,我开始赏金寻找这个问题的最优雅的解决方案。

理想的解决方案应该理想地满足以下标准:

  1. 一个注释可在所有枚举上重复使用
  2. 从注释实例中检索默认枚举值作为枚举的最小工作量/复杂性

迄今为止最好的解决方案

沙丘:

@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 以获取提供的默认值。

这需要为每个枚举类型创建一个注解类型,但保证编译时检查类型的安全性。

最佳答案

如果构造函数参数中未提供该值,但不关心运行时的泛型类型,则不完全确定您所说的获取默认值是什么意思。

以下内容有效,但有点丑陋。

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();
}
}

编辑:我将 getDefaultValue 更改为通过枚举的 valueOf 方法工作,因此如果给定的值不是枚举的引用实例,则会给出更好的错误消息。

关于java - Java枚举注解值的枚举默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7071301/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com