1

我需要从一个集合中创建一个EnumSet 。我决定使用EnumSet#copyOf方法。但是,由于此方法的限制:

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

我需要确保集合不为空。然后代码变为:

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);

也许 javac 在确定传递给方法的集合成员的正确类型方面存在真正的限制copyOf,但我无法克服我必须诉诸上述方法来满足空集合的感觉。这是我的问题:

  1. 究竟是什么限制,这里不能接受空集合?

  2. 像这样的方法签名copyOf(Collection<Enum<E>>)会解决这个问题吗?

  3. 如果是,它还会产生什么其他问题?

4

2 回答 2

0

鉴于EnumSet.copyOf 空集合抛出 IllegalArgumentException,似乎有用的是接受元素类型参数的复制构造函数,这在创建新 EnumSet 时是必需的:

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

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

虽然节省的费用很小,但清晰度的提高是显着的。对比:

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

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

目的只是将给定的集合复制为 EnumSet。这种意图的简单、直接的表达似乎是最合适的。

于 2019-04-30T16:31:01.097 回答
0

查看 的源代码EnumSet,我发现需要至少一个元素的两个原因copyOf(Collection)

  • 检查类的enum可能enum值的数量。此数字用于确定使用哪个实现:RegularEnumSet使用单个中的位long来标记包含的元素(最多允许 64 个值),JumboEnumSet使用long[]( longarray)。
  • 元素的类型被存储并用于运行时类型检查(例如,add(E)子类调用EnumSet.typeCheck(E)中的方法可以抛出一个ClassCastException)。由于类型擦除,这似乎是必要的。

像这样的方法签名copyOf(Collection<Enum<E>>)会解决这个问题吗?

签名基本上已经是您所建议的,只是语法不同:

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

这里E被定义为<E extends Enum<E>>Collection<E>某种类型的Collection<Enum<E>>.

于 2016-07-20T10:23:40.970 回答