The maximum number of constants in an enum compiled by javac is currently about 2740 (*). The limiting factor is the size of the <clinit>, which instantiates each enum constant and write it to a field, and also initialize the values array.
(*) e.g. 2746 for 1.8.0_202-b08 and 2743 for 14+36-1461, the difference is caused by the constant pool order affecting when ldc_w becomes necessary to load strings for constant names
Moving the creation of the values array to a helper method allows enums to have about 4103 constants.
i.e. instead of:
private static final T[] #VALUES = { a, b, c };
we would have:
private static final synthetic T[] #values() { return new T[] { a, b, c }; }
private static final T[] #VALUES = #values();
This is similar to what ecj is already doing: instead of saving the values array to a static field that's initialized in the <clinit>, it just re-creates the array for every call to values(). That may be worth considering, although it may also have performance implications vs. initializing the values array upfront and using clone().
(*) e.g. 2746 for 1.8.0_202-b08 and 2743 for 14+36-1461, the difference is caused by the constant pool order affecting when ldc_w becomes necessary to load strings for constant names
Moving the creation of the values array to a helper method allows enums to have about 4103 constants.
i.e. instead of:
private static final T[] #VALUES = { a, b, c };
we would have:
private static final synthetic T[] #values() { return new T[] { a, b, c }; }
private static final T[] #VALUES = #values();
This is similar to what ecj is already doing: instead of saving the values array to a static field that's initialized in the <clinit>, it just re-creates the array for every call to values(). That may be worth considering, although it may also have performance implications vs. initializing the values array upfront and using clone().