10/31/2006

Custom String Values for Enum

The default string value for java enum is its face value, or the element name. However, you can customize the string value by overriding toString() method. For example,

public enum MyType {
ONE {
public String toString() {
return "this is one";
}
},

TWO {
public String toString() {
return "this is two";
}
}
}
Running the following test code will produce this:
public class EnumTest {
public static void main(String[] args) {
System.out.println(MyType.ONE);
System.out.println(MyType.TWO);
}
}

this is one
this is two
Another interesting fact is, once you override toString() method, you in effect turn each element into an anonymous inner class. So after compiling the above enum class, you will see a long list of class files:
MyType.class
MyType$1.class
MyType$2.class

13 comments:

Anonymous said...

Thanks, i was just looking for this since my naive approach (overriding toString in the scope of the enum) didn't work!

Anonymous said...

I believe a better approach would have been to provide a constructor for your enumeration:

public enum Xyz {
A("Hello"), B("Goodbye");
private Xyz(String name) {
this.name = name;
}
private final String name;
public String toString() {
return name;
}
}

In fact you can give your constructors any number of parameters of any type and supply additional methods on your enumerations to access those values.

This also prevents the anonymous inner class issue you noted.

Anonymous said...

Why not use override toString for the whole enum?

public enum ABC {

Y, N;

@Override
public String toString() {
if (this == Y) return "yes";
else return "no";
}
}

javahowto said...

The second comment gives a more compact implementation of custom string value (see his/her example enum Xyz). And in most cases, it's a better approach. The advantage of the approach described in the blog post is it allows each element to customize its display, at a more fine-grained level. If we were to do it at the whole enum level, we would have to conditionize it, which is not very OO.

Anonymous said...

Note that all these examples will break the round-trip enum<->string as you cannot change the behavior of the static method Enum.valueOf().

Xyz.toString () may give you the desired output, but Enum.valueOf () will not.

Of course, if you don't need to turn a string back into an enum, or you can guarantee all callers will use your class' impl of valueOf, you're golden.

It really is a shame that ordinal value cannot be explicitly defined.

javahowto said...

Good point. valueOf(String name) only takes the identifier name, not the toString() value.

Anonymous said...

if you want the round trip enum<->string you can use the valueOf()/name() combination.

The name method returns the exact string identifier for that enum value.

Anonymous said...

thank you for the post and for the comment #2. Both were very good!

Phazonaddict said...

public enum Type
{
NORMAL, FIRE, WATER, THUNDER, ICE,
GRASS, GHOST, DARK, GROUND, STEEL,
WIND, PSYCHIC, POISON, MAGIC, ROCK,
FIGHTING, LIGHT, COSMIC, RAINBOW;

public String toString()
{
String output = name().toString(); // Example: NORMAL
output = output.charAt(0) + output.substring(1).toLowerCase();

return output; // Output: Normal
}
}


From a program I'm writing, this should allow both the value and the string to work fine.

Fletch said...

If you have a simple case like phazonaddict mentioned, is there any genuine value in the solutions on this page as opposed to just using "Normal", "Fire", "Water" etc as your Enum values?

Obviously you feel nice if you use capitals since Sun tells you to do that. But there's also value in simplicity of code. Thoughts...?

Aneesh said...

public String toString() {
if (this.name == null)
return super.toString();

return name;
}

Phazonaddict said...

Fletch, I just happened to stumble upon this again. I guess I am just used to using capitals for enum identifiers.
... no, not because Sun says so, but because my lecturers did :P

To be honest though, it does help their values stand out. (to me)

Also, I posted my comment because I thought people might find it handy.
Obviously it's a simple solution, but you never know...

Blaise said...

It's a valid example of use if, for example you wanted to do something more complicated thatn just capitalisation, eg adding a space then another word to every value...