I have stumbled into this by accident. Here is the short story. In some code-base there are a bunch of enums that follow the same pattern, here is one that is greatly simplified:
enum Letters {
A("a"),
Z("z");
private String value;
Letters(String value) {
this.value = value;
}
private static final Map<String, Letters> MAP;
public String getValue() {
return value;
}
static {
MAP = Arrays.stream(values())
.collect(Collectors.collectingAndThen(
Collectors.toMap(
Letters::getValue,
Function.identity()
),
ImmutableMap::copyOf
));
}
public static Optional<Letters> fromValue(String value) {
return Optional.ofNullable(MAP.get(value));
}
}
This is a pattern across tens of Enums, literally, and no this can't be changed. I thought about changing this code duplication, since it's a lot of it.
My idea was to start with an enum interface, that all will implement:
interface GetValueInterface {
String getValue();
}
And some common code that will handle this MAP creation (fromValue
would be handled there too, but let's put that aside). So, something like this:
static class EnumsCommon {
public static <T extends Enum<T> & GetValueInterface> Map<String, T> getAsMap(Class<T> clazz) {
T[] values = clazz.getEnumConstants();
return Arrays.stream(values)
.collect(Collectors.collectingAndThen(
Collectors.toMap(
T::getValue,
Function.identity()
),
ImmutableMap::copyOf
));
}
}
So the code looks like this now:
enum Letters implements GetValueInterface {
// everything else stays the same
static {
MAP = EnumsCommon.getAsMap(Letters.class);
}
}
This compiles just fine, but when I run it under java-8
, there is an exception thrown:
Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Enum; not a subtype of implementation type interface GetValueInterface
Running the same code under java-11
works just fine...