Factoring of a method that appears in many enumerations

I have several enumerations with the name and byName , which is approximately the same for all of them:

 public static Condition byName(String name) throws NotFoundException { for (Condition c : values()) { if (c.name.equals(name)) { return c; } } throw new NotFoundException("Condition with name [" + name + "] not found"); } 

Since the byName method byName duplicated in different enumerations, I would like to include it in one place and avoid code duplication.

But:

  • Enumerations cannot extend an abstract class
  • Java8 interfaces with default methods cannot access values() method

I know that this could probably be done with AspectJ, but I would prefer not to introduce compilation in time for something simple, and this is Spring AOP (which I have at hand, since this is a Spring project). only allows you to bind to existing methods and not add new ones.

Any other viable solution to add a generic enumeration method?

+5
source share
3 answers

Here is what I did in the same situation:

 public interface EnumWithNames { String getName(); static <E extends EnumWithNames> E byName(Class<E> cls, String name) { for (E value : cls.getEnumConstants()) { if (Objects.equals(value.getName(), name)) return value; } throw new IllegalArgumentException("cannot identify " + cls.getName() + " value by name " + name); } } public enum Condition implements EnumWithNames { private String name; ... @Override public String getName() { return name; } } 

And when I need to find the value of an enumeration by name, I call:

 Condition c = EnumWithNames.byName(Condition.class, "Name 1"); 

Note cls.getEnumConstants() same as values() .

+7
source

Looks like I'm a little late for the party here ... but here is what I have for this occasion:

  static interface Nameable { static <T extends Enum<T>> T byName(Class<T> clazz, String name) { return EnumSet.allOf(clazz) .stream() .filter(i -> i.name().equals(name)) .findFirst() .orElseThrow(IllegalArgumentException::new); } } 
+2
source

You can create some kind of static utility method and use the utility method inside enum itself. You still have a little duplication. Not sure of a much better way to do this.

 public static T staticByName(String name, Class<T> clazz) { for (T c : values()) { if (c.name.equals(name)) { return c; } } throw new NotFoundException("Condition with name [" + name + "] not found"); } 

and in the listing

 public static Condition byName(String name){ return Utility.staticByName(name, Condition.class); } 

Alternatively, you can put elements on the map into an Enum instance to make it more efficient.

The code above is not verified, so you may have to modify it to work with Enums, but it gets this idea.

0
source

Source: https://habr.com/ru/post/1262942/


All Articles