Java enums will be enhanced with generics support and with the ability to add methods to individual items, a new JEP shows. Since both features can be delivered with the same code change, they are bundled together in the same JEP. The change only affects the Java compiler, and therefore no runtime changes are needed. Although there is no target version, Java 10 seems likely.

The change didn't initially get a postive reaction, with prominent Java Champions like Joshua Bloch questioning its usefulness. However, some further discussion and the presentation of new uses cases helped it gain support.

In case you didn't see my resp to @BrianGoetz, I now see the point of the JEP and withdraw my objections. Use case:https://t.co/O1tJO8oSCp — Joshua Bloch (@joshbloch) December 7, 2016

Let's now show what the changes would allow the developer to do by summarising some of the use cases presented in the JEP and other discussions. Java Champion Lukas Eder presented a StackOverflow question that introduced a case for retrieving and setting properties from a config file, web session, or similar, in a type-safe manner. An enum with generics support would allow us to indicate the set of available keys together with their associated type:

public enum Key<T> { HOST<String>, PORT<Integer>, SCORE<Double> } public interface PropertiesStore { public <T> void put(Key<T> key, T value); public <T> T get(Key<T> key); }

Now these keys can be safely retrieved and stored from and into the properties store, since expressions like the following will fail to compile:

put(PORT, “not a number”); // error, type mismatch: PORT is Key<Integer> // “not a number” is String

On the other hand, allowing individual items to have their own methods can help define operations that apply only to certain properties. Under JEP 301, the above definition could be expanded as follows:

public enum Key<T> { HOST<String>, PORT<Integer>, SCORE<Double> { double normalise(double x) { // score normalisation logic return result; } } }

With the current enums, all the items would have the generic type Key , which means the method normalise wouldn't be visible. However, after this work is finished, the compiler would preserve this kind of information, which means the following would be true:

SCORE.normalise(5.37); // compiles HOST.normalise(5.37); // error: neither HOST nor Key have normalise

The way to accomplish this will be by changing how the exposed static type of the individual items of the enum is calculated. As the reader may know, enums were added in Java 5 as mere syntactic sugar: the JVM doesn't have any special treatment for enums, instead, the compiler translates an enum into a normal class with static objects, and then compiles this into bytecode. Putting aside some technical aspects, the following enum:

public enum Colour { RED, GREEN, BLUE }

Is roughly translated by the compiler to the following (this isn't an accurate representation, but it's close enough for the purpose of this explanation):

public class Colour extends Enum { public static final Colour RED = new Colour(); public static final Colour GREEN = new Colour(); public static final Colour BLUE = new Colour(); private Colour() {} }

Since the type of all the items is Colour , any item-specific method or type information is lost. What JEP 301 will do is identify the cases where using the generic enum type is not enough to represent the individual items, and in such cases generate further, more specific types like Colour$RED , Colour$GREEN and Colour$BLUE .

Enhanced enums may benefit even further from other work being currently carried out in other parts of the JDK. On one side, local variable type inference might allow developers to get hold of the sharper types created by the compiler even though the exact form of these is unknown at the time of writing code; this would mean that, considering the code above, the following would be possible:

var s = Key.SCORE; // type of s derived as Key$SCORE s.normalise(8.29); // method normalise can be accessed

On the other side, anecdotical evidence and sample use cases suggest that generics in enums might be extensively used with primitive types, which is rather inefficient (the JVM has to use the boxed counterpart for each primitive type). This could be improved with the part of Project Valhalla that deals with Generics over Primitive Types, removing this barrier and making it available for mass utilisation.

Update: About Sharper Types