枚举值上的Java注释:将注释实例传递给用户代码
我们有一个枚举类型,其中有很多条目。每个枚举值都有一些布尔(或其他)属性,大多数在90%的情况下具有相同的值。我们最终得到了如下代码:枚举值上的Java注释:将注释实例传递给用户代码,java,enums,annotations,Java,Enums,Annotations,我们有一个枚举类型,其中有很多条目。每个枚举值都有一些布尔(或其他)属性,大多数在90%的情况下具有相同的值。我们最终得到了如下代码: enum Foo { A(true, false, false, true), B(false, false, false, true), C(false, false, false, false); final boolean f1; final boolean f2; final boolean f3;
enum Foo {
A(true, false, false, true),
B(false, false, false, true),
C(false, false, false, false);
final boolean f1;
final boolean f2;
final boolean f3;
final boolean f4;
Foo(boolean f1, boolean f2, boolean f3, boolean f4) {
this.f1 = f1;
this.f2 = f2;
this.f3 = f3;
this.f4 = f4;
}
}
这需要编写大量代码,而且很难阅读(“第三位的布尔值又是什么意思?”)
这似乎是注释的一个用例:
@Retention(RetentionPolicy.RUNTIME)
@interface Flags {
boolean f1() default false;
boolean f2() default false;
boolean f3() default false;
boolean f4() default false;
}
enum Foo {
@Flags(f1=true)
A,
@Flags(f4=true)
B,
@Flags()
C;
final boolean f1;
final boolean f2;
final boolean f3;
final boolean f4;
Foo(boolean flag1, boolean f2, boolean f3, boolean f4) {
try {
Flags flags = Objects.requireNonNull(Foo.class.getField(name()).getAnnotation(Flags.class),
"Annotation for '"+getClass().getSimpleName()+"."+name()+"' is missing!");
this.f1 = flags.f1();
this.f2 = flags.f2();
this.f3 = flags.f3();
this.f4 = flags.f4();
} catch (NoSuchFieldException|SecurityException e) {
// should not happen
throw new RuntimeException(e);
}
}
}
但是这个不能短一点吗
enum Foo {
@Flags(f1=true)
A,
@Flags(f4=true)
B,
@Flags()
C;
final Flags flags;
Foo(boolean flag1, boolean f2, boolean f3, boolean f4) {
try {
this.flags = Objects.requireNonNull(Foo.class.getField(name()).getAnnotation(Flags.class),
"Annotation for '"+getClass().getSimpleName()+"."+name()+"' is missing!");
} catch (NoSuchFieldException|SecurityException e) {
// should not happen
throw new RuntimeException(e);
}
}
}
当然,现在我们必须使用bar.flags.f1()
而不是bar.f1()
。例如:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
public class Scratch {
@Retention(RetentionPolicy.RUNTIME)
@interface Flags {
boolean key() default false;
boolean visible() default true;
}
enum Foo {
@Flags(key = true)
A,
@Flags(visible = false)
B;
final Flags flags;
Foo() {
try {
this.flags = Objects.requireNonNull(Foo.class.getField(name()).getAnnotation(Flags.class),
"Annotation for '" + getClass().getSimpleName() + "." + name() + "' is missing!");
} catch (NoSuchFieldException | SecurityException e) {
// Sollte nicht vorkopmmen
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
for (Foo bar : Foo.values()) {
System.out.format("%s: key=%-8svisible=%-8s%n", bar.name(), bar.flags.key(), bar.flags.visible());
}
}
}
以及输出:
A:key=true可见=true
B:键=假可见=假
除了不同的语法之外,还有什么理由不传递注释实例吗?或者有没有更优雅的解决方案(不涉及使用框架)?虽然我不是直接回答您关于注释的问题,但我是在回答您问题的核心(正如您所写:或者有没有更优雅的解决方案(不涉及使用框架)?)。我不同意这种情况是使用注释的好地方 我建议你考虑一下达到预期模式的更优雅的方式:
public enum Foo {
A(FF.F1, FF.F4),
B(FF.F4),
C();
enum FF {
F1, F2, F3, F4;
}
boolean f1;
boolean f2;
boolean f3;
boolean f4;
Foo(FF... flags) {
for (FF ff : flags)
switch (ff) {
case F1:
f1 = true;
break;
case F2:
f2 = true;
break;
case F3:
f3 = true;
break;
case F4:
f4 = true;
break;
}
}
}
或者更简单:
public enum Foo {
A(FF.F1, FF.F4),
B(FF.F4),
C();
enum FF {
F1, F2, F3, F4;
}
boolean[] f = new boolean[FF.values().length];;
Foo(FF... flags) {
for (FF ff : flags) {
f[ff.ordinal()] = true;
}
}
}
枚举不要求是不可变的:
enum Foo {
A(){{f1(); f2();}},
B(){{f4();}},
C;
private boolean f1;
private boolean f2;
private boolean f3;
private boolean f4;
private void f1() {f1 = true;}
private void f2() {f2 = true;}
private void f3() {f3 = true;}
private void f4() {f4 = true;}
}
这或多或少地实现了您的意图,同时隐藏了细节。您不是在传递“注释实例”,而是在传递一个几乎是标准Java的类型。我不确定我是否理解这个问题。@DaveNewton我传递了
Foo.flags
,它是注释类型的对象。我只是不知道这是否是预期的用例。对,你正在传递一个类型。这和传递其他类型的信息没有什么不同。