java - 使用通用接口(interface)实例化枚举集合的单行代码

标签 java generics collections enums

我有两个实现通用接口(interface)的枚举。我尝试声明该接口(interface),以便只有枚举可以实现它。

interface CommonEnumInterface<E extends Enum<?>> {

    /** It doesn't matter what this does. */
    E commonInterfaceMethod();

}

enum Enum1 implements CommonEnumInterface<Enum1> {
    FOO,
    BAR,
    BAZ;

    @Override
    public Enum1 commonInterfaceMethod() {
        return null;
    }
}

enum Enum2 implements CommonEnumInterface<Enum2> {
    BLAH,
    YADDA,
    RHUBARB;

    @Override
    public Enum2 commonInterfaceMethod() {
        return Enum2.BLAH;
    }
}

现在我想创建另一个枚举,其中每个常量都有自己的 CommonEnumInterface 类型的元素集,但不一定是同一个类。不过,我发现的每一种方法都感觉像是一种黑客攻击,特别是在我希望每个常量都用多个元素集声明的情况下。

这些评论显示了我已经尝试过的内容。有没有更优雅的方式(编译)?

enum CreatingAnotherEnumAttempt {

    // Type mismatch: cannot convert from List<Enum<?>&CommonEnumInterface<?>> to List<CommonEnumInterface<?>>
    A(Arrays.asList(Enum1.FOO, Enum2.BLAH)),

    // Cannot cast from List<Enum<?>&CommonEnumInterface<?>> to List<CommonEnumInterface<?>>
    B((List<CommonEnumInterface<?>>) Arrays.asList(Enum1.FOO, Enum2.BLAH)),

    // This works, but it generates type safety warnings, and it's hard to read.
    C(Arrays.asList((CommonEnumInterface<?>) Enum1.FOO, (CommonEnumInterface<?>) Enum2.BLAH)),

    // This is the best I've come up with.
    D(getMixOfElements(Enum1.FOO, Enum2.BLAH));

    /**
     * I want to populate this set in the constructor.
     */
    private final Set<CommonEnumInterface<?>> mixOfElements;

    /**
     * I tried declaring the Set this way, but wildcards can extend only one interface, so there's a syntax error at the ampersand.
     */
    private final Set<? extends Enum<?> & CommonEnumInterface<?>> mixOfElements;

    /**
     * This is the constructor I'm trying to satisfy.
     *
     * @param mixOfElements I could make this a varargs parameter, but that only works for a single set of elements. What if I want more?
     */
    private CreatingAnotherEnumAttempt(List<CommonEnumInterface<?>> mixOfElements) {
        this.mixOfElements = Collections.unmodifiableSet(new HashSet<CommonEnumInterface<?>>(mixOfElements));
    }

    /**
     * This method only exists to allow method {@link #D}. It's pretty pointless, otherwise.
     *
     * @param mixOfElements the mix of elements
     * @return the mix of elements as a list
     */
    private static List<CommonEnumInterface<?>> getMixOfElements(CommonEnumInterface<?>... mixOfElements) {
        return Arrays.asList(mixOfElements);
    }

    /**
     * This works without type safety warnings or superfluous methods, but for my constructor, I need a one-liner.
     */
    private static void wayThatWorksInline() {
        Collection<CommonEnumInterface<?>> inlineWay = new ArrayList<CommonEnumInterface<?>>();
        inlineWay.add(Enum1.FOO);
        inlineWay.add(Enum2.BLAH);
    }

}

我的问题在上面,在代码注释中。一般来说,这是声明我的接口(interface)的正确方法吗?

最佳答案

涉及枚举的事实实际上是一种转移,因为只需传递 List<CommonEnumInterface<?>>进入构造函数是你的目标。为此,请执行以下操作:

A(Arrays.<CommonEnumInterface<?>>asList(Enum1.FOO, Enum2.BLAH)),

//etc.

问题是类型推断 - 有时它有点太急切了。基于论据Enum1.FOOEnum2.BLAHasList ,编译器推断 Enum<?>&CommonEnumInterface<?>对于 T ,等等 List<Enum<?>&CommonEnumInterface<?>>被退回。自 generics aren't covariant ,这不能分配给 List<CommonEnumInterface<?>> 。指定 T 的类型参数手动解决此问题。

关于java - 使用通用接口(interface)实例化枚举集合的单行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21035711/

相关文章:

c# - 如何使用 json.net 将 C# 通用列表转换为 json?

java - 如何在Java中创建字符和动态ArrayList的映射

java - HashSet顺序及与JDK 7/8的区别

Java 集合性能问题

java - 在java中比较byte[i]和string

java - 检查Java中是否加载了包(API)

JAVA - 通过扩展线程类实现多线程 - 关于创建对象

c++ - 在 C++ 中实现泛型堆栈

java - 如何将 d3 (javascript) 添加到 vaadin 应用程序?

swift - NSCountedSet 泛型函数