Use attributes and interfaces on Java enums

Most Java developers know of Java enums. Most developers also know that each field of an enum can define its own methods. But even most of those who know that are not aware they can define a contract each field of the enum must implement.

It might seem a useless piece of information. Yet, in my own case, it was really useful to me…

What and why?

What?

OK, so before going further, having an enum which would be a basis for the rest of this post. Let’s remain basic and take the first enum the Oracle documentation proposes.

Why?

OK, so now we have an enum, but why the heck would we want its fields to implement methods.

Let’s take once more the Oracle documentation as an example:

OK, this works just fine. Something bothers me, though: why should the class using the enum be the one to tell how the name should be displayed to the user? Isn’t that an attribute of the enum?

Let us think of it: every class using the Day enum to display it to users will have to use a switchon its values and determine the String value to represent it. And what if someone discovered an eighth day in the week (OK, not likely, but this is because I poorly chose my example)? Every single of these classes should be rewritten… No, not a good idea.

Time for another solution then.

Our purpose in this post

I would really like you to understand the greatest interest of this, so here is our goal: write a method which prints the name of all days in a week.

It may seem trivial and, once more, useless, but not that much. This was inspired from my own needs in a GWT application: making a combo box from an enum. If you can print all values of an enum, you can build such a widget.

Now, at the current stage of the example, consider what we would have to do to achieve such a feat:

Take a look at the highlighted lines. That will be what your program will display if you had a value to the enum and forget to update the methods using it. What about modularity?!

Time for something better…

Adding attributes to enum values

How to do it

If Day was an abstract class, and each Day value a subclass of Day, we could define a label field for Day, and a constructor subclasses would have to use when instantiated. Then, we would just add a getter for this label for other classes to use…

Day would then look like the following:

Oh but wait! Don’t you know? We can! Two tips to remember though:

  • the constructor cannot be used outside the enum (you wouldn’t one anybody to create new values to your enum!) so it must be declared private;
  • since you have declared only one constructor, all values must use it, which is done through passing the arguments beside the value declaration.

We thus end up with something like this:

You’re done!

Does it meet our need?

Remember our printDayNames methods above. Now, here is a new version that should work just fine:

A mere loop. No more switch. Everything automatic.

Forcing each value to implement a method

Context

As I said before, this post is the result from experimentations I made due to a need in a GWT application. I might have forgot to say: a localized GWT application.

As such, the label value is not static and depends on the locale. We have a message bundle (which I will call Labels), with all proper tools. Now, we should tell the enum to use this bundle instead of a predefined value.

However, to do that, the enum must have access to the bundle, so it must be passed as an argument to a method. And to be sure I will be able to use this method on any value, I should define it at the Day level.

Solution

Quite simple actually! Remember what we discovered previously: an enum behaves just like an abstract class! (yes, I dared use a bold typeface, but this is probably the most important tip of the post)

So here we go with a new solution: create an abstract method that all values will have to implement.

And does it really works?

Of course it does! Here’s how (I highlighted the changes since previous version):

Using an interface

What more can I wish for?

The printDayNames method is great, but it works only for Day. I have several enums with the same problematic. Should I do this for all?

Of course, you will have to implement the getLabel method for each enum value you want to print. But everything else can be brought back to using an interface and generics. Don’t believe me?

The solution

The interface first:

Simple, right? Now, just edit your enum to implement it:

Now, we will create the method inspired from our previous printDayNames, using generics :

Granted, you now have to provide an argument to the method, but you have one method for all Displayable objects. The way to do this will be to call the method as follows:

Using this principle, I was able to create a generic combo box for all Displayable enums, instead of creating manually one for each enum. It works just fine.

Hope I have helped you. Comment and share your own tips!

Published by

Cyrille Chopelet

Programming addict, UX philosopher, casual gamer, sci-fi enthusiast, hi-tech dilettante, ... Some people even call me a geek.

"Wit beyond measure is man's greatest treasure." − Rowena Ravenclaw

This site uses Akismet to reduce spam. Learn how your comment data is processed.