首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用相同方法的多个Java 8枚举

使用相同方法的多个Java 8枚举
EN

Stack Overflow用户
提问于 2017-09-08 04:15:18
回答 2查看 3.1K关注 0票数 2

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

代码语言:javascript
复制
/* 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?,它有一个使用接口的示例,但我不知道如何处理构造函数和静态方法。我也不知道如何在fromDB()方法中删除对类型BoneDiagnosis的显式引用。

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

代码语言:javascript
复制
public enum BoneDiagnosisComplexTypeDefinition {
    NORMAL(121),
    ELEVATED(207);
    OSTEOPENIA(314),
    OSTEOPOROSIS(315)
}
EN

回答 2

Stack Overflow用户

发布于 2017-09-08 07:00:59

您可以使用以下命令最小化每个enum的代码和每个操作的开销

代码语言:javascript
复制
@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));
    }
}
代码语言:javascript
复制
public enum BoneDiagnosis implements Common {
    @DbId(121) NORMAL,
    @DbId(207) ELEVATED,
    @DbId(314) OSTEOPENIA,
    @DbId(315) OSTEOPOROSIS;
}

测试用例

代码语言:javascript
复制
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类型。

票数 6
EN

Stack Overflow用户

发布于 2017-09-08 04:27:19

这个解决方案仍然有一些样板桥接代码。

使用Interface定义调用接口,并在某个类中实现公共代码。下面是一个简单的例子:

文件: BoneDiagnosis.java

代码语言:javascript
复制
public enum BoneDiagnosis
implements
    CommonStuffs
{
  NORMAL(121),
  ELEVATED(207),
  OSTEOPENIA(314),
  OSTEOPOROSIS(315);

  private CommonStuffsImpl commonStuffsImpl;
  private int value;

  BoneDiagnosis(final int theValue)
  {
      value = theValue;

      commonStuffsImpl = new CommonStuffsImpl();
  }

  @Override
    public int toDB()
  {
    return commonStuffsImpl.toDBImplementation(value);
  }
}

文件: CommonStuffs.java

代码语言:javascript
复制
public interface CommonStuffs
{
    int toDB();
}

文件: CommonStuffsImpl.java

代码语言:javascript
复制
public class CommonStuffsImpl
{
    public int toDBImplementation(
        final int value)
    {
        return value;
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46104419

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档