Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enums shared static look-up method

Tags:

java

enums

I have the following Enum:

public enum MyEnum{
    A(10, "First"), //
    B(20, "Second"), //
    C(35, "Other options");

    private Integer code;
    private String description;

    private MyEnum(Integer code, String description) {
        this.code = code;
        this.description = description;
    }

    public Integer getCode() {
        return code;
    }

    public String getDescription() {
        return description;
    }

    public static MyEnum getValueOf(Integer code) {
        for (MyEnum e : MyEnum.values()) {
            if (e.getCode().equals(code)) {
                return e;
            }
        }
        throw new IllegalArgumentException("No enum const " + MyEnum.class.getName() + " for code \'" + code
                + "\'");
    }
}

Which works fine. The getValueOf-method exists because when communicating with an external partner, we only get the code (they chose) to map to. I need the description because I need to show a meaningfull phrase in the GUI.

But I now have a number of similar enum classes. All having their own code & description, and they need the same lookup functionality. I wanted the getValueOf-method to be generic so I don't need to support 30+ different enums for basically the same method.

To solve this I wanted to make an abstract class to define this method and implement some of the common logic but this is impossible because I can't extend Enum.

Then I tried to make a Utility class with the following method:

public static <T extends Enum<T>> T getValueOf(Enum<T> type, Integer code) {...}

But generics with Enums are confusing and I don't understand how to get this working.

Basically what I want to know is: What is a good approach to define a common utility to an enum?

like image 558
Boosty Avatar asked Apr 12 '12 10:04

Boosty


People also ask

Can enums static methods?

The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared.

How can I lookup a Java enum from its string value?

Example: Lookup enum by string value We then use the enum TextStyle's valueOf() method to pass the style and get the enum value we require. Since valueOf() takes a case-sensitive string value, we had to use the toUpperCase() method to convert the given string to upper case.

Can we call == to compare enums?

There are two ways for making comparison of enum members :equals method uses == operator internally to check if two enum are equal. This means, You can compare Enum using both == and equals method.

Does enum valueOf throw exception?

The valueOf() enum method converts a specified string to an enum constant value. An exception is thrown if the input string doesn't match an enum value.


2 Answers

You need to pass the actual enum class object as a parameter to your method. Then you can get the enum values using Class.getEnumConstants().

In order to be able to access getCode() on the instances, you should define it in an interface and make all your enum types implement that interface:

interface Encodable {     Integer getCode(); }  public static <T extends Enum<T> & Encodable> T getValueOf(Class<T> enumClass, Integer code) {     for (T e : enumClass.getEnumConstants()) {         if (e.getCode().equals(code)) {             return e;         }     }     throw new IllegalArgumentException("No enum const " + enumClass.getName() + " for code \'" + code             + "\'"); }  ...  public enum MyEnum implements Encodable {     ... }  MyEnum e = getValueOf(MyEnum.class, 10); 
like image 183
Péter Török Avatar answered Sep 22 '22 07:09

Péter Török


This is a bit tricky because the values() method is static. You would actually need reflection, but there is a nice way to hide this using standard library functionality.

First, define an interface with the methods common to all of your enum types:

public interface Common {     Integer getCode();     String getDescription(); } 

Then, make all your enums implement this interface:

public enum MyEnum implements Common {...} 

The static method you want to have then looks like:

public static <T extends Enum<T> & Common> T getValueOf( Class<T> type, Integer code ) {     final EnumSet<T> values = EnumSet.allOf( type );     for(T e : values) {         if(e.getCode().equals( code )) {             return e;         }     }     throw new IllegalArgumentException( "No enum const " + type.getName() + " for code \'" + code + "\'" ); } 
like image 31
Michael Schmeißer Avatar answered Sep 20 '22 07:09

Michael Schmeißer