首页 > 解决方案 > 如何获得在 Java 中实现特定接口的正确枚举?

问题描述

我有以下界面:

public interface Moon {
    // Enums can not extend any class in Java,
    // thus I am implementing an interface
    double getMass();
    double getDiameter();
}

由我的枚举实现(我省略了构造函数和方法实现)

public enum Saturn implements Moon {
    ATLAS(30.2, 6.6),
    PAN(28.2, 4.95);

    private double Diameter;
    private double Mass;

    // constructor and methods implementation
}

以及其他行星的类似枚举:

public enum Mars implements Moon {
    PHOBOS(22.2, 1.08),
    DEIMOS(12.6, 2);

    private double Diameter;
    private double Mass;

    // constructor and methods implementation
}

问题

有两个字符串:

String planetName = "Mars";
String moonName = "PHOBOS";

如何以聪明的方式获得特定的枚举?

在只有一个枚举类的情况下,它是该valueOf方法的简单使用,但是如何检查实现特定接口的所有枚举?

Moon something = <??planetName??>.valueOf(moonName);

标签: javaenums

解决方案


您可以使用行星名称到相关枚举类型的映射,并使用它来执行查找。

例如,使用地图(肯定有替代方法):

Map<String, Class<? extends Enum>> planetMoonTypes = new HashMap<>();

planetMoonTypes.put("Saturn", Saturn.class);
planetMoonTypes.put("Mars", Mars.class);

使用这样的地图,您可以使用以下方法查找"PHOBOS"值:

Moon phobos = (Moon) Enum.valueOf(planetMoonTypes.get("Mars"), "PHOBOS");

以上将返回Mars.PHOBOS


编辑:关于添加非月球枚举的能力。您可以封装地图并强制设置适当的界限。例如,以下使用一种方法:

class MoonRegistry {

    private final Map<String, Class<? extends Enum>> 
              planetMoonTypes = new HashMap<>();

    {
        this.registerEnum("Saturn", Saturn.class);
        this.registerEnum("Mars", Mars.class);
    }

    public <T extends Enum<T> & Moon> void registerEnum(
            String planetName, Class<T> cls) {
        this.planetMoonTypes.put(planetName, cls);
    }

    public Moon findByPlanetAndName(String planet, String name) {
        return (Moon) Enum.valueOf(this.planetMoonTypes.get(planet), name);
    }
}

同样,这个解决方案不能是完全类型安全的,因为有多个枚举子类型(如您所见,原始Enum类型在实例字段的类型中)。但是,如果这被正确封装并且您的代码不使用此类之外的原始类型,则可以确保仅Moon添加实现的枚举类型。


推荐阅读