Are enum names interned in Java?
I.e. is it guaranteed that enum1.name() == enum2.name()
in case of the same name? And is it safe to compare enum.name()
to a String that is guaranteed to be interned.
A Java enum is a data type that stores a list of constants. You can create an enum object using the enum keyword. Enum constants appear as a comma-separated list within a pair of curly brackets. An enum, which is short for enumeration, is a data type that has a fixed set of possible values.
In Java, there should only be one instance of each of the values of your enum in memory. A reference to the enum then requires only the storage for that reference. Checking the value of an enum is as efficient as any other reference comparison.
The name() method of Enum class returns the name of this enum constant same as declared in its enum declaration. The toString() method is mostly used by programmers as it might return a more easy to use name as compared to the name() method.
Because they are constants, the names of an enum type's fields are in uppercase letters. You should use enum types any time you need to represent a fixed set of constants.
Although there is no explicit guarantee of this, the end result is bound to be such that the comparison always succeeds for enum
constants with identical names:
enum A {enum1}; enum B {enum1}; System.out.println(A.enum1.name() == B.enum1.name()); // Prints "true"
The reason for this is that Java compiler constructs subclasses of Enum
in such a way that they end up calling Enum
's sole protected constructor, passing it the name of enum
value:
protected Enum(String name, int ordinal);
The name is embedded into the generated code in the form of a string literal. According to String
documentation,
All literal strings and string-valued constant expressions are interned.
This amounts to an implicit guarantee of your expression succeeding when names of enum
constants are identical. However, I would not rely on this behavior, and use equals(...)
instead, because anyone reading my code would be scratching his head, thinking that I made a mistake.
Dasblinkenlight's answer is the best answer we have so far. There he says:
The reason for this is that Java compiler constructs subclasses of
Enum
in such a way that they end up callingEnum's
sole protected constructor, passing it the name ofenum
value
and there they get interned, because they're string constants.
But, in the JLS, 8.9.2, Enum Body Declarations, there's this:
In practice, a compiler is likely to mirror the
Enum
type by declaringString
andint
parameters in the default constructor of anenum
type. However, these parameters are not specified as "implicitly declared" because different compilers do not need to agree on the form of the default constructor. Only the compiler of anenum
type knows how to instantiate theenum
constants; other compilers can simply rely on the implicitly declaredpublic static
fields of theenum
type (§8.9.3) without regard for how those fields were initialized.
(emphasis mine)
So we'll call the constructor, but we aren't forced to do it in any particular way, and we can manage our own constructor in the compiler.
Therefore, it's completely possible for me to write a correct and JLS-compliant Java compiler that would not intern the names somehow, probably by not having the names stored as a literals. Yes, it would do it on purpose to maliciously break your code, but it would be correct behaviour per spec.
Every sane implementation will intern the strings. I'd say it's safe to assume this kind of behaviour. It's not guaranteed, though, and therefore if I saw this in real code, I'd be very unsatisfied with it even if it was thoroughly described in a comment.
Please, don't rely on such unspecified and implementation-specific behaviour. If you really, really have to, write a unit test for it. And put an assert
in the code, and lots of explaining. Measure whether your approach will actually do anything.
Consider looping over the This doesn't work reliably. See comments.enum
members' names and intern()
them manually before using them. That way, it will be immediatelly clear what you're doing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With