如何获得在 Java 中实现特定接口的正确枚举?

mat*_*ked 5 java enums

我有以下界面:

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

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

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
}
Run Code Online (Sandbox Code Playgroud)

对于其他行星也有类似的枚举:

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

    private double Diameter;
    private double Mass;

    // constructor and methods implementation
}
Run Code Online (Sandbox Code Playgroud)

问题

有两个字符串:

String planetName = "Mars";
String moonName = "PHOBOS";
Run Code Online (Sandbox Code Playgroud)

如何以智能方式获取特定枚举?

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

Moon something = <??planetName??>.valueOf(moonName);
Run Code Online (Sandbox Code Playgroud)

ern*_*t_k 2

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

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

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

planetMoonTypes.put("Saturn", Saturn.class);
planetMoonTypes.put("Mars", Mars.class);
Run Code Online (Sandbox Code Playgroud)

使用这样的映射,您可以"PHOBOS"使用以下方式查找值:

Moon phobos = (Moon) Enum.valueOf(planetMoonTypes.get("Mars"), "PHOBOS");
Run Code Online (Sandbox Code Playgroud)

上面会返回Mars.PHOBOS


编辑:关于添加非 Moon 枚举的能力。您可以封装地图并强制执行正确的边界。例如,以下使用了一种方法:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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