A Reversible Enum, from Atif Khan

Home

News: A Reversible Enum, from Atif Khan

  1. A Reversible Enum, from Atif Khan (15 messages)

    Atif Khan points out how useful the enum keyword is for Java, but says that having the ability to look up an enum by its value - a reversible enum - would be useful as well. In this blog entry, he shows a pattern by which one can use a Map to look up the actual enum represented by a value. One can see this being useful in cases where a web application accepts a value from a list or checkbox from a user; a reversible enum would allow an easy mechanism to convert HTML values to internal values. For example, this could eliminate some of the need for converters for elements whose values are known ahead of time - such as colors, boolean values, country selection, etc. What do you think of the technique? Many people have used similar techniques manually; having it expressed as a pattern like this seems like a broadly useful and applicable idea. Should it be part of the JVM, as Mr. Khan suggests?

    Threaded Messages (15)

  2. Uh. Enum.valueOf?
  3. Calling Enum.valueOf does a reverse lookup for the name of the Enum, not its internal value. The blog entry discusses a technique to get Enum instances from the internal value. In my opinion, looking up Enums this way defeats the whole purpose of having an Enum in the first place. The internal value of the Enum is not intended to be exposed.
  4. I am doing this as well[ Go to top ]

    I am doing this for my project as well. I defined a reference base class with a registry, the enum is extension of reference base, I used this enum to build HTML select by giving a list of items in the enum. After the user submits the form, my domain class need to resolve whih enum item the user chose, so I defined a valueOf(String key) to lookup the enum item. Since I am using 1.4, they are not exactly enum yet but the same concept can be applied to enum in java 5 as well, for this sake, the enum should be improved to cater for this purpose. This results in once only once pattern and it is a great way to define constants.
  5. Reverse lookups *are* useful[ Go to top ]

    If those numbers are internal use only, why can we assign them arbitrary values? The primary use case that comes to mind for reverse lookups is when retrieving enumerated values from a database. Imagine you have a customer, with a status field. The status can be ACTIVE (0), INACTIVE(1) or CLOSED(2). This is obviously an ideal candidate for a CustomerStatus enum. You probably want to persist and retrieve customer instances from a database table. You will typically want to store the underlying integral value (0,1,2) - either for efficiency or because you're dealing with an existing schema. When you fetch a record back from the database, how do you reconsititue the enumerated type? Same thing applies for webservice interfaces or any other marshalling layer where you're not jsut serializing Java objects. It's suprising (and frankly quite crazy) that Java 5's Enum doesn't support this out of the box.
  6. I agree, reverse lookups are useful[ Go to top ]

    I use them all the time, for web forms, web services, anywhere I lose my typed value in transmission. I was inspired by the chapter on enums in Josh Block's Effective Java when I came up with this. Here's a sample of code, I actually was dissapointed by the java 5 valueOf implementation, so i ended up keeping this form: import java.lang.reflect.Field; import java.util.Collections; import java.util.HashMap; import java.util.Map; //-------------------------------- // Generated code. Do not edit. //-------------------------------- public final class AddressType { public static final AddressType HOME = new AddressType("HOME"); public static final AddressType OFFICE = new AddressType("OFFICE"); public static final AddressType LEGAL = new AddressType("LEGAL"); public static final AddressType PREVIOUS_LEGAL = new AddressType("PREVIOUS_LEGAL"); public static final AddressType MAIL = new AddressType("MAIL"); public static final AddressType INTP = new AddressType("INTP"); private final String value; private AddressType(String value) { this.value = value; } private static final Map _values; static { Map map = new HashMap(); Class thisClass = AddressType.class; Field[] fields = thisClass.getFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; if (field.getType() == thisClass) { try { Object o = field.get(field.get(null)); map.put(o.toString(), o); } catch (IllegalAccessException e) { e.printStackTrace(); } } } _values = Collections.unmodifiableMap(map); } public static AddressType valueOf(String name) { return (AddressType) _values.get(name); } public String getValue() { return value; } public String toString() { return value; } }
  7. "I actually was dissapointed by the java 5 valueOf implementation" Your implementation does essentially the same thing as Enum.valueOf. The enum type is more or less an improved descendant of Effective Java's.
  8. public enum Type { TYPE1(0), TYPE2(1); private Long ID; private Type(final long ID) { this.ID = Long.valueOf(ID); } public static final Type fromLong(final Long l) { for (final Type t : EnumSet.allOf(Type.class)) { if (t.ID.equals(l)) { return t; } } throw new EnumConstantNotPresentException(Type.class, l.toString()); } public final Long longValue() { return ID; } }
  9. "Calling Enum.valueOf does a reverse lookup for the name of the Enum, not its internal value. The blog entry discusses a technique to get Enum instances from the internal value." Duh, We are in agreement about this being retarded. Exposing the ordinal value is fine, but not using it for storage or anything else. There's no point in having the enum if you aren't going to use the symbol, If you really wanted to, you could get call FooEnum.values() and find it.
  10. enum is fine , but..[ Go to top ]

    i think Java5 enum's are fine and very strong, but they can be enhanced like: - As Joshua Bloch noted, they could implement Comparable interface. (maybe in Java 7?) - A convenience method for retrieving the enums or it's string-int values as a Set or Map. Many times i want to check if a String is a representation of the enum or not, but there is no convenience method. valueOf(String s) throws an exception if s does not exist. - Some optimizations (i think Java6 has them.). For example, if i am not mistaken, in Java5, values() creates an array each time it is invoked. an internal static array could be easily used.
  11. Re: enum is fine , but..[ Go to top ]

    "valueOf(String s) throws an exception if s does not exist." ...this is my major concern.
  12. You can pass in the value you want to retrieve the enum for and by looping through the enums till it is found and return it. public enum CustomType { CustomTypeS("S"), CustomTypeO("O"), CustomTypeL("L"); private String code; private CustomType(String c) { this.code = c; } /** * Given a value it retrieves the given enum * assigned to that value. * @param value the value you want to find enum for * @return the custom type enum specified by the value */ public static CustomType getEnum(String value) { for(CustomType type : values()) { if (type.code.equals(value)) { return type; } } throw new EnumConstantNotPresentException(CustomType.class, "The custom type for value '" + value + "' does not exist."); } } Example usage: SomeObjectNeedingEnum.setCustomType(CustomType.getEnum("O"); Which should return 'CustomType.CustomTypeO'.
  13. not so convenient.[ Go to top ]

    You can pass in the value you want to retrieve the enum for and by looping through the enums till it is found and return it.
    yes, but this is hardly effective and not really convenient. i think it is better to provide a boolean valueExist(String s); method.
  14. Re: not so convenient.[ Go to top ]

    You can pass in the value you want to retrieve the enum for and by looping through the enums till it is found and return it.


    yes, but this is hardly effective and not really convenient. i think it is better to provide a

    boolean valueExist(String s);

    method.
    Convenient?
    In my mind, not really. I think that every situation requires a different set of priorities or functionality. In my particular case if the type can't be found I want an exception.

    Effective?
    Well, what you are suggesting only applies to the implementation I suggested and not really to the topic at hand. So I don't see how it is ineffective as it accomplishes its intended goal. Might I suggest you posting what you think is more effective that accomplishes the goal of the topic? Maybe everyone has missed the obvious.
  15. well[ Go to top ]

    Convenient?
    In my mind, not really. I think that every situation requires a different set of priorities or functionality. In my particular case if the type can't be found I want an exception.

    Effective?
    Well, what you are suggesting only applies to the implementation I suggested and not really to the topic at hand. So I don't see how it is ineffective as it accomplishes its intended goal. Might I suggest you posting what you think is more effective that accomplishes the goal of the topic? Maybe everyone has missed the obvious.
    Well, why throw an exception? Collections contains method does not throw an exception after all. i would prefer a check before find. i prefer it this way. For effectiveness , you are probably right, i guess scanning an array is more effective then finding in a Map (assuming if it is implemented internally in a future Java version) for small amount of enum parameters, which is the case most of the times.
  16. Many people above say that one should never use the internal value of an enum. So to those people I ask: What data type should one use when implementing a communication protocol where specific constants are specified by the protocol? Let's say you have a communication interface to some piece of hardware and this communication protocol is a binary protocol, i.e., not XML. Using enums whose integral values you can fetch allows you to write the code you have to write in a more type-safe manner than defining constants in an interface.