I would like to enforce that the elements of a Java Enum are chosen or excluded from an EnumSet at compile time
i.e. I am forced to make the decision to put it in the set or not whenever I create a new element for my Enum.
i.e. a new element on the Enum won’t compile unless deliberately added or excluded.
I thought I was being very clever by making the choice dependent on a constructor parameter like this (the last parameter):
public enum MyFileType {
DOT_CSV("csv", "text/csv", true),
DOT_XLS("xls", "application/vnd.ms-excel", true),
DOT_XLSX("xlsx", "application/vnd.ms-excel", true),
UNRECOGNISED(null, null, false);
/** Makes sure TYPES is initialised first. */
private static class AllowedFileTypes {
private static final Set<MyFileType> TYPES =
EnumSet.noneOf(MyFileType.class);
}
public final String fileExtension;
private final String mailContentType;
private MyFileType(final String newExtension,
final String newMailContentType,
final boolean allowed) {
fileExtension = newExtension;
if (allowed) {
AllowedFileTypes.TYPES.add(this);
}
}
}
I thought I was being very clever because exceptionally for classes, when the Enum class is initialised, the constructors are called first so that the Enum has elements, and only then are the static fields initialised.
This meant I couldn’t simply have a static field with an EnumSet for my ‘allowed types’.
Putting the TYPES field in a static class beats this – the static class initialises first.
Therefore in theory I figured it would be possible to add the element into the AllowedTypes set. However there is a big hitch – EnumSet can only be instantiated by a call to one of its factory methods, and the factory methods want to see all the elements.
So at runtime, at this point the Enum is not initialised, it has no elements yet, and EnumSet decides that it can’t be an Enum and throws a ClassCastException.
Technically I think it should throw some variation of IllegalStateException, but that is beside the point.
Therefore I can’t use this approach to initialising my AllowedTypes EnumSet. I could resort to using a straight-forward HashSet
and initialising it on demand, but that’s not elegant really.
How else can I achieve my goal?