Beware of Enum.values()!

Since we’re expanding on various oddities… With J2SE Enum hashCode() returns the identity hash code on Android hashCode() returns the ordinal + hash code of the String name of the enum. Doh! If you try and mix a lot of Enum with other objects returning the identity hash code on Android collisions potentially occur. Also if you have two Enum classes with a duplicate name in the same position the hash codes collide. Doh!

On Android:


    @Override
    public final int hashCode() {
        return ordinal + (name == null ? 0 : name.hashCode());
    }

I was a curious and made a few tests because I thought escape analysis would simply take care of this as long as you don’t keep a reference to the Enum.values(). But it doesn’t. It seems escape analysis only works for primitive arrays as a VarArg parameter.

VarArgs are ok IF they are primitive and smaller than 64 elements, then they are simply allocated on the stack. Here is a link to a test program, with escape analysis that specific test is a 110 times faster! But it doesn’t seem to work for object arrays :confused:

Defensive copies of objects returned or temp objects work rather well though.

The lack of documentation and JIT compiler makes it really hard to test this stuff.

It could be argued that if you’ve got a varargs argument in a performance critical section of code you’re maybe not writing performance aware code in the first place of course.

Cas :slight_smile:

Thanks!!! I was about to use Enum.values() for my singleton explosion class.

I’d meant to link to that article earlier and forgot. However, where are you getting the “doesn’t seem to work for object arrays” from? The linked article doesn’t seem to imply that, so wondered about the test. I would have thought the JIT compiler could easily inline the object references to remove the array, even if not inlining fields from the objects themselves!?

hmm … yes and no … potentially. I read another article recently (and can’t remember the damn link) which suggested varargs could be faster than passing in a cached array because escape analysis might remove the array access code too.

Have I added in enough "could"s, "suggested"s, "might"s and “pray to the magic fairy” in all that? ;D

I was more thinking along the lines of, if you’re calling a fairly generic function that’s meant to take arbitrary parameters, but you are in performance critical code and already know in advance what your parameters are… may as well optimise that properly.

Cas :slight_smile: