tags:

views:

1466

answers:

2

In Java, you can create an enum as follows:

public enum Letter {
    A, B, C, D, E, F, G;

    static {
       for(Letter letter : values()) {
          // do something with letter
       }
    }
}

This question concerns the "values()" method. Specifically, how is it implemented? Usually, I could jump to the source for Java classes using F3 or CTRL+Click in Eclipse (even for classes like String, Character, Integer, and even Enum). It is possible to view the source of the other enum methods (e.g., valueOf(String)).

Does "values()" create a new array each time it is invoked? If I assign it to a local variable and then modify one of the elements, what happens (clearly this won't affect the value returned by values(), which implies that a new array is allocated each time).

Is the code for it native? Or does the JVM / compiler treat it specially, only returning a new instance from values() when it cannot prove that it will not be modified.

Thanks in advance.

Cheers, LES

+10  A: 

Basically, the compiler (javac) translates your enum into a static array containing all of your values at compile time. When you call values(), it gives you a .clone'd() copy of this array.

Given this simple enum:

public enum Stuff {
   COW, POTATO, MOUSE;
}

You can actually look at the code that Java generates:

public enum Stuff extends Enum<Stuff> {
    /*public static final*/ COW /* = new Stuff("COW", 0) */,
    /*public static final*/ POTATO /* = new Stuff("POTATO", 1) */,
    /*public static final*/ MOUSE /* = new Stuff("MOUSE", 2) */;
    /*synthetic*/ private static final Stuff[] $VALUES = new Stuff[]{Stuff.COW, Stuff.POTATO, Stuff.MOUSE};

    public static Stuff[] values() {
        return (Stuff[])$VALUES.clone();
    }

    public static Stuff valueOf(String name) {
        return (Stuff)Enum.valueOf(Stuff.class, name);
    }

    private Stuff(/*synthetic*/ String $enum$name, /*synthetic*/ int $enum$ordinal) {
        super($enum$name, $enum$ordinal);
    }
}

You can look at how javac 'translates' your classes by making a temporary directory and running:

javac -d <output directory> -XD-printflat filename.java
lucasmo
A: 

If you assign it to a local variable the only thing that you can modify is assigning another enum to this variable. This will not change the enum itself because you are only changing the object your variable references.

It seems that the enums are in fact singletons so that only one element from each enum can exist in you whole program this makes the == operator legal for enums.

So there is no performance problem and you can't accidentally change something in your enum definition.

Janusz
i think the OP means modifying the array returned by values(). if this is the same array object that is kept internally (instead of a copy), then modifying it (e.g. assigning one element to another, assigning null to an element, etc.) would mess it up, not only for the enum class, but for any future calls to values()
newacct
Yes you are right. If there wasn't a clone you could remove a Enum from the array and later calls from values would miss this value.
Janusz