How can I get the proper enum that implements a particular interface in Java?

  • A+
Category:Languages

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.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: