views:

407

answers:

5

Curious if anybody has considered using EnumMap in place of Java beans, particularly "value objects" (with no behavior)? To me it seems that one advantage would be that the name of a "property" would be directly accessible from the backing Enum, with no need for reflection, and therefore I'd assume it would be faster.

+2  A: 

A bean is meant to be mutable, hence the setter methods. EnumMap is comparable in speed to using a HashMap with integers as the Key, but are Keys are Immutable. Beans and EnumMaps serve two different purposes. If all of the Keys are known at design time and are guaranteed to never change, then using an EnumMap will be fine.
Updating a bean is much simpler than changing the backing Enum of the EnumMap with much less chance of creating errors downstream in the code.

WolfmanDragon
I don't think that's what OP meant. Instead of `setAge()` bean setter you'd call `myMap.put(MyFieldNames.AGE, age)`. `EnumMap` is very "mutable" in that sense.
ChssPly76
@ChssPly76, edited answer to address this.
WolfmanDragon
I'll clarify my point. The fact that EnumMap keys are immutable is irrelevant - OP compares them to property (and, ergo, method) names which are "immutable" by definition, just like they are "known at design time". Both method names and EnumMap keys may change; if they do you'll have to change code in both cases. Updating a bean is not simpler then adding another field to enum; errors in dependent code will be triggered either way (e.g. wrong method name or undefined symbol for missing enum constant). The biggest difference (and the biggest problem in EnumMap approach) is type safety.
ChssPly76
+1  A: 

It may be a little faster then using reflection (I didn't measure it, didn't find any metrics in Google either); however there are big disadvantages to this approach:

  1. You're losing type safety. Instead of int getAge() and String getName() everything is Object get(MyEnum.FIELD_NAME). That'll provide for some ugly code and run-time errors right there.

  2. All the javabean niceties we've come to love and enjoy (for example, property-level annotations) are gone.

  3. Since you can have NO BEHAVIOR AT ALL, the applicability of this approach seems rather limited.

The bottom line is - if you really truly need that alleged :-) boost in performance (which you'll have to measure to prove it exists) this may be a viable approach under very specific circumstances. Is it a viable alternative to javabeans at large? Most certainly not.

ChssPly76
if you have generics, enumMap's get() method returns the correct type.
Chii
It still will only return a single type for all keys.
Kathy Van Stone
@kathy: true that =)
Chii
A: 

I had not previously specified this, but I am working with a ResultSet. Therefore I want to provide this answer for the sake of completeness.

Commons/BeanUtil's "RowSetDynaClass" could be the happy medium between the excessive boilerplate associated with concrete beans, and the limitations of EnumMap

George Jempty
A: 

I don't understand how you can remove 'class profileration' with EnumMaps. Unless you have a generic enum with 20-odd properties to reuse for every 'bean', you're still inventing an enum to use for each enum map, e.g.

public enum PersonDTOEnum {
     A, S, L;
}

as opposed to

class Person {

    int a;
    int s;
    String l;

    // getters + setters elided
}

Not to mention that everything is a String now.

Robert Munteanu
+1  A: 

I wrote a Record class that maps keys to values and works by delegating to a fully synchronized EnumMap. The idea is that a Record can get new fields at runtime whereas the Bean can't. My conclusion is that with this flexibility comes a performance hit. Here's a run comparing the Record class to a fully synchronized Bean. For 10 million operations:

Record  set(Thing, a)  458 ms
Bean    setThing(a)    278 ms
Record  get(Thing)     398 ms
Bean    getThing       248 ms

So, there is something to gain in knowing your data objects and writing a class that models them statically. If you want to have new fields padded on to your data at runtime, it will cost you.

kiwicptn