【问题标题】:Java generics with multiple enums implementing an interface具有多个实现接口的枚举的 Java 泛型
【发布时间】:2019-03-08 17:06:35
【问题描述】:

我想将枚举类列表传递给一个方法,其中所有枚举都实现一个公共接口,并让该方法返回枚举值之一。

Java Generics Wildcarding With Multiple Classes,好像是

public class Main
{
    interface Foo {}

    enum First implements Foo {
        A, B, C;
    }

    enum Second implements Foo {
        X, Y, Z;
    }

    interface Bar {}

    enum Third implements Bar {
        M, N, P;
    }
    enum Fourth implements Bar {
        A, X, Z;
    }


    public static <I, T extends Enum<?> & I> 
      I enumVarArgs(Class<? extends T>... classes) 
    {
        // Do stuff and return some instance of T
        return null;
    }

    public static void main(String[] args) {
        Foo foo = enumVarArgs(First.class,
                              Second.class);
        Bar bar = enumVarArgs(Third.class,
                              Fourth.class);
    }
}

应该做我想做的事。但是,这无法在 Java 10 下编译:

[ERROR] /me/test/src/main/java/test/Main.java:[17,42] error: unexpected type
  required: class
  found:    type parameter I
  where I,T are type-variables:
    I extends Object declared in method <I,T>enumVarArgs(Class<? extends T>...)
    T extends Enum<?>,I declared in method <I,T>enumVarArgs(Class<? extends T>...)
[INFO] 1 error

从错误消息中,我猜 Java 希望我做类似T extends Enum&lt;?&gt; &amp; Serializable 的事情,我在其中传递一个实际的接口,而不是一个类型参数。但是,我需要 API 是通用的,以便 I 保持通用参数。

有没有一种语法可以让这个工作?

如果重要的话,我们使用的是 Java 10。

【问题讨论】:

  • 您知道您的 A 和 X 会有所不同吗?即 First.a!=Fourth.a

标签: java generics enums


【解决方案1】:

如果接口是你的设计,那么你可以让这两个接口扩展一个标记接口:

interface FooBar{}

interface Foo extends FooBar {}

interface Bar extends FooBar {}

你可以使用这个标记界面:

public static <T extends Enum<?> & FooBar> 
      FooBar enumVarArgs(Class<? extends T>... classes) {
    return null;
}

【讨论】:

  • 声明 I extends FooBar 并返回 I 意味着您需要在此方法中从 FooBarI 进行未经检查的强制转换
  • @yyyy 完全正确。我肯定没有明白这一点,因为我不必实现该方法。谢谢,我已经删除了第二个解决方案。
【解决方案2】:

我认为你需要的是:

interface OnlyImpelents<T> {}
interface Foo extends OnlyImpelents<Foo> {}
interface Bar extends OnlyImpelents<Bar> {}

static <T extends Enum<?> & OnlyImpelents<? super T>> T enumVarArgs(T... values) {
    return values[0];
}
public static void main(String[] args) {
    Foo foo = enumVarArgs(First.A, Second.X);
}

标记接口OnlyImpelents&lt;T&gt; 阻止任何类同时实现FooBar

从枚举类中获取枚举值的唯一方法是通过反射,它不需要具有静态类型。个人觉得这不是一个好的面向对象设计,使用T...作为args应该会更好

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多