gpt4 book ai didi

java - 具有相同方法的多个 Java 8 枚举

转载 作者:行者123 更新时间:2023-11-29 10:09:38 25 4
gpt4 key购买 nike

我有一系列枚举,除了名称和值不同外,它们看起来像这样:

/* Bone Diagnosis. Value is internal code stored in database. */
public enum BoneDiagnosis {
NORMAL(121),
ELEVATED(207),
OSTEOPENIA(314),
OSTEOPOROSIS(315);

private int value;
BoneDiagnosis(final int value) {
this.value = value;
}

/** Get localized text for the enumeration. */
public String getText() {
return MainProgram.localize(this.getClass().getSimpleName().toUpperCase() + ".VALUE." + this.name());
}

/** Convert enumeration to predetermined database value. */
public int toDB() {
return value;
}

/** Convert a value read from the database back into an enumeration. */
public static BoneDiagnosis fromDB(final Integer v) {
if (v != null) {
for (final BoneDiagnosis pc : values()) {
if (v == pc.toDB()) {
return pc;
}
}
}
return null;
}
}

我知道我不能扩展枚举,但是有什么方法可以抽象这个设计来删除每个类在 toDB()、fromDB() 和 getText() 中的所有重复代码吗?我查看了其他问题,例如 Is it possible to extend enum in Java 8?其中有一个使用接口(interface)的示例,但我无法弄清楚如何处理构造函数和静态方法。我也不知道如何在 fromDB() 方法中删除对类型 BoneDiagnosis 的显式引用。

我的梦想是让每个类都像下面这样定义,所有其他支持都包含在 BoneDiagnosisComplexTypeDefinition 中。这可能吗?

public enum BoneDiagnosisComplexTypeDefinition {
NORMAL(121),
ELEVATED(207);
OSTEOPENIA(314),
OSTEOPOROSIS(315)
}

最佳答案

您可以最小化每个枚举代码和使用

的每个操作开销
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME)
public @interface DbId {
int value();
}
final class Helper extends ClassValue<Map<Object,Object>> {
static final Helper INSTANCE = new Helper();

@Override protected Map<Object, Object> computeValue(Class<?> type) {
Map<Object,Object> m = new HashMap<>();
for(Field f: type.getDeclaredFields()) {
if(f.isEnumConstant()) try {
Object constant = f.get(null);
Integer id = f.getAnnotation(DbId.class).value();
m.put(id, constant);
m.put(constant, id);
}
catch(IllegalAccessException ex) {
throw new IllegalStateException(ex);
}
}
return Collections.unmodifiableMap(m);
}
}
public interface Common {
String name();
Class<? extends Enum<?>> getDeclaringClass();
default int toDB() {
return (Integer)Helper.INSTANCE.get(getDeclaringClass()).get(this);
}
default String getText() {
return MainProgram.localize(
getDeclaringClass().getSimpleName().toUpperCase() + ".VALUE." + name());
}
static <T extends Enum<T>&Common> T fromDB(Class<T> type, int id) {
return type.cast(Helper.INSTANCE.get(type).get(id));
}
}
public enum BoneDiagnosis implements Common {
@DbId(121) NORMAL,
@DbId(207) ELEVATED,
@DbId(314) OSTEOPENIA,
@DbId(315) OSTEOPOROSIS;
}

测试例子

int id = BoneDiagnosis.OSTEOPENIA.toDB();
System.out.println("id = " + id);
BoneDiagnosis d = Common.fromDB(BoneDiagnosis.class, id);
System.out.println("text = " + d.getText());

请注意,反射操作仅使用 ClassValue 在每个类中执行一次,它专门设计用于有效地缓存每个类的元数据,线程安全并且不会在重要的环境中阻止类卸载。实际的 toDBfromDB 被简化为散列查找。

顺便说一句,这段代码使用 getDeclaringClass() 而不是 getClass() 很重要,因为枚举可能具有特殊化,例如 enum Foo { BAR { … } … 其中 getClass() 返回特化类而不是 enum 类型。

关于java - 具有相同方法的多个 Java 8 枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46104419/

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