I have the following interface:
public interface Moon {
// Enums can not extend any class in Java,
// thus I am implementing an interface
double getMass();
double getDiameter();
}
that is implemented by my enums (I omitted the constructor and methods implementation)
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
}
and similarly enums for other planets:
public enum Mars implements Moon {
PHOBOS(22.2, 1.08),
DEIMOS(12.6, 2);
private double Diameter;
private double Mass;
// constructor and methods implementation
}
Question
Having two strings:
String planetName = "Mars";
String moonName = "PHOBOS";
How can I obtain the particular enum in a smart way?
In the case of only one enum class it is a simple use of the valueOf
method, but how can I check all enums that implement a particular interface?
Moon something = <??planetName??>.valueOf(moonName);
You can use a mapping of planet names to related enum types, and use that to perform a lookup.
For example, using a map (there are surely alternative approaches):
Map<String, Class<? extends Enum>> planetMoonTypes = new HashMap<>();
planetMoonTypes.put("Saturn", Saturn.class);
planetMoonTypes.put("Mars", Mars.class);
With such a map, you can lookup the "PHOBOS"
value using:
Moon phobos = (Moon) Enum.valueOf(planetMoonTypes.get("Mars"), "PHOBOS");
The above will return Mars.PHOBOS
EDIT: Regarding the ability to add non-Moon enums. You can encapsulate the map and force proper bounds. For example, the following uses a method for that:
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);
}
}
Again, this solution cannot be fully type-safe because there are multiple enum subtypes (as you can see, the raw Enum
type is in the type of the instance field). But if this is properly encapsulated and your code uses no raw types outside this class, you can ensure that only enum types implementing Moon
are added.
If you really want it to be dynamic, you could achieve this using Reflection, event if I don't recommend it. You could either
Mars
to another package, it will break. Mars
which implements Moon
and look for the instance. This is kind of overkill.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With