How can I eliminate duplicated Enum code?

后端 未结 15 828
眼角桃花
眼角桃花 2020-12-24 13:40

I have a large number of Enums that implement this interface:

/**
 * Interface for an enumeration, each element of which can be uniquely identified by its co         


        
相关标签:
15条回答
  • 2020-12-24 14:12

    Create a type-safe utility class which will load enums by code:

    The interface comes down to:

    public interface CodeableEnum {
        String getCode();
    }
    

    The utility class is:

    import java.lang.reflect.InvocationTargetException;
    
    
    public class CodeableEnumUtils {
        @SuppressWarnings("unchecked")
        public static <T extends CodeableEnum>  T getByCode(String code, Class<T> enumClass) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
            T[] allValues = (T[]) enumClass.getMethod("values", new Class[0]).invoke(null, new Object[0]);
            for (T value : allValues) {
                if (value.getCode().equals(code)) {
                    return value;
                }
            }
            return null;
    }
    

    }

    A test case demonstrating usage:

    import junit.framework.TestCase;
    
    
    public class CodeableEnumUtilsTest extends TestCase {
        public void testWorks() throws Exception {
        assertEquals(A.ONE, CodeableEnumUtils.getByCode("one", A.class));
          assertEquals(null, CodeableEnumUtils.getByCode("blah", A.class));
        }
    
    enum A implements CodeableEnum {
        ONE("one"), TWO("two"), THREE("three");
    
        private String code;
    
        private A(String code) {
            this.code = code;
        }
    
        public String getCode() {
            return code;
        }   
    }
    }
    

    Now you are only duplicating the getCode() method and the getByCode() method is in one place. It might be nice to wrap all the exceptions in a single RuntimeException too :)

    0 讨论(0)
  • 2020-12-24 14:12

    In my opinion, this would be the easiest way, without reflection and without adding any extra wrapper to your enum.

    You create an interface that your enum implements:

    public interface EnumWithId {
    
        public int getId();
    
    }
    

    Then in a helper class you just create a method like this one:

    public <T extends EnumWithId> T getById(Class<T> enumClass, int id) {
        T[] values = enumClass.getEnumConstants();
        if (values != null) {
            for (T enumConst : values) {
                if (enumConst.getId() == id) {
                    return enumConst;
                }
            }
        }
    
        return null;
    }
    

    This method could be then used like this:

    MyUtil.getInstance().getById(MyEnum.class, myEnumId);
    
    0 讨论(0)
  • 2020-12-24 14:13

    How about a static generic method? You could reuse it from within your enum's getByCode() methods or simply use it directly. I always user integer ids for my enums, so my getById() method only has do do this: return values()[id]. It's a lot faster and simpler.

    0 讨论(0)
提交回复
热议问题