1

I need to create an EnumSet from a Set. I decided to use the EnumSet#copyOf method. However, because of a restriction on this method:

the specified collection must contain at least one element (in order to determine the new enum set's element type)

I need to ensure that the collection is not empty. The code then becomes:

enum Color {RED, GREEN, BLUE}; Set<Color> set = ... // get it from somewhere if (set.isEmpty()) { return EnumSet.noneOf(Color.class); else return EnumSet.copyOf(set);

Perhaps there is a real limitation on javac to determine the correct type of members of the collection passed to copyOf method, but I can't get over the feeling that I have to resort to something like above to cater for the empty collection. Here are my questions then:

  1. Exactly what is the limitation that the empty collection can't be accepted here?

  2. Would a method signature like copyOf(Collection<Enum<E>>) have solved this problem?

  3. If yes, what other problems would it have created?

Kedar Mhaswade
  • 4,535
  • 2
  • 25
  • 34

2 Answers2

0

Looking at the source code of EnumSet, I see two reasons to require at least one element for copyOf(Collection):

  • The enum class is checked for the number of possible enum values. This number is used to determine which implementation is used: RegularEnumSet uses the bits in a single long to mark the contained elements (allowing up to 64 values), JumboEnumSet uses a long[] (long array).
  • The type of the element is stored and used for a runtime type check (for example, the add(E) method in the subclasses calls EnumSet.typeCheck(E) which can throw a ClassCastException). This seems to be necessary due to type erasure.

Would a method signature like copyOf(Collection<Enum<E>>) have solved this problem?

The signature already is basically what you suggest, just with different syntax:

public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c)

Here E is defined as <E extends Enum<E>> which means Collection<E> is some type of Collection<Enum<E>>.

Martin
  • 2,573
  • 28
  • 22
0

In light of EnumSet.copyOf empty collection throws IllegalArgumentException, what would seem to be of use would be a copy constructor which accepted an element type parameter, as is necessary when creating a new EnumSet:

EnumSet(Class<E>elementType, Enum<?>[] universe)

public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c, Class<E> elementType);

While the savings are small, the gain in clarity is significant. Contrast:

if ( set.isEmpty() )
  return EnumSet.noneOf(Color.class);
else
  return EnumSet.copyOf(set);

return EnumSet.copyOf(set, Color.class);

The intent is simply to copy a given set as an EnumSet. A simple, direct, expression of that intent seems most appropriate.

Thomas Bitonti
  • 1,179
  • 7
  • 14