Suppose you’re maintaining an API that was originally released years ago (before java gained enum support) and it defines a class with enumeration values as ints:
public class VitaminType { public static final int RETINOL = 0; public static final int THIAMIN = 1; public static final int RIBOFLAVIN = 2; }
Over the years the API has evolved and gained Java 5-specific features (generified interfaces, etc). Now you’re about to add a new enumeration:
public enum NutrientType { AMINO_ACID, SATURATED_FAT, UNSATURATED_FAT, CARBOHYDRATE; }
The ‘old style’ int-enum pattern has no type safety, no possibility of adding behaviour or data, etc, but it’s published and in use. I’m concerned that mixing two styles of enumeration is inconsistent for users of the API.
I see three possible approaches:
-
Give up and define the new enum (
NutrientTypein my fictitious example) as a series of ints like theVitaminTypeclass. You get consistency but you’re not taking advantage of type safety and other modern features. -
Decide to live with an inconsistency in a published API: keep
VitaminTypearound as is, and addNutrientTypeas anenum. Methods that take aVitaminTypeare still declared as taking an int, methods that take aNutrientTypeare declared as taking such. -
Deprecate the
VitaminTypeclass and introduce a newVitaminType2enum. Define the newNutrientTypeas an enum.
Congratulations, for the next 2-3 years until you can kill the deprecated type, you’re going to deal with deprecated versions of every single method that took aVitaminTypeas an int and adding a newfoo(VitaminType2 v)version of each. You also need to write tests for each deprecatedfoo(int v)method as well as its correspondingfoo(VitaminType2 v)method, so you just multiplied your QA effort.
What is the best approach?
Personal opinion is that it’s probably not worth the effort of trying to convert. For one thing, the ‘public static final int’ idiom isn’t going away any time soon, given that it’s sprinkled liberally all over the JDK. For another, tracking down usages of the original ints is likely to be really unpleasant, given that your classes will compile away the reference so you’re likely not to know you’ve broken anything until it’s too late (by which I mean
gets compiled into
So if you rewrite A you may not ever realize that B is broken until you recompile B later.
It’s a pretty well known idiom, probably not so terrible to leave it in, certainly better than the alternative.