Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Factoring out a method appearing across many enums [duplicate]

I have several enums with a name property and a byName method which is roughly like this 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 is duplicated across different enums, I'd like to factor it out in a single place and avoid duplicated code.

However:

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

I know this could probably be done with AspectJ, but I'd rather not introduce compile-time weaving for something simple as this, and Spring AOP (which I have at hand since this is a Spring project) only allows binding to existing methods and not adding new ones.

Any other viable solution to add a common method to enums?

like image 608
Raibaz Avatar asked Jan 17 '17 15:01

Raibaz


1 Answers

Here's 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 enum value by name I call:

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

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

like image 193
Yaroslav Stavnichiy Avatar answered Sep 21 '22 18:09

Yaroslav Stavnichiy