如何构建一个通用varargs的EnumSet?

时间:2016-07-23 23:47:13

标签: java generics

假设我想做以下事情:

public static <V> Set<V> setOf(V... elem)
{
    Set<V> set = null;  
    if (elem[0] instanceof Enum)
        set = Sets.newEnumSet(elem, elem[0].getClass());  OR
        set = EnumSet.<V>noneOf(elem[0].getClass());
    return set;
}

这些或其他几种变体似乎都不起作用。有人可以向我解释发生了什么事吗?我查看了How do I get the type object of a genericized Enum?和其他一些类似的问题,但我仍然无法使其发挥作用。

2 个答案:

答案 0 :(得分:1)

首先,您需要确保类型V被限制为枚举类型;您可以通过指定V必须extends Enum<V>

来执行此操作

然后,您需要提供枚举类型的Class。由于类型擦除,您无法在运行时获取它。这是必需的,因为要构造一个新的空EnumSet,您需要指定元素的类型。

最后,您有几种方法可以创建集合,但最简单的方法可能是使用Stream API:

@SafeVarargs
public static <V extends Enum<V>> Set<V> setOf(Class<V> enumClass, V... elem) {
    return Arrays.stream(elem).collect(Collectors.toCollection(() -> EnumSet.noneOf(enumClass)));
}

请注意,如果您可以保证至少有1个元素,则可以使用EnumSet.copyOf(Arrays.asList(elem))而无需传递该类。

答案 1 :(得分:0)

如果您无法将通用参数绑定到V extends Enum<V>,则可以按如下方式编写可编译代码:

public <V> Set<V> setOf(V... elem) {
    Set<V> set = null;
    if (elem[0].getClass().isEnum()) {
        set = (Set<V>) EnumSet.copyOf((Collection<Enum>)Arrays.asList(elem)) ;
    }
    return set;
}

当然有不安全的演员警告。

我还将类型检查更改为:

if (elem[0].getClass().isEnum())
恕我直言的更清洁。