通用边界“Enum<T> & Foo”和“Enum<之间有区别吗?扩展 Foo>”

2022-09-03 07:41:17

以下两个(有效的)泛型边界是:

<T extends Enum<T> & MyInterface>
<T extends Enum<? extends MyInterface>>

一样?


假设我有一个接口

interface MyInterface {
    void someMethod();
}

以及实现它的一些枚举:

enum MyEnumA implements MyInterface {
    A, B, C;
    public void someMethod() {}
}

enum MyEnumB implements MyInterface {
    X, Y, Z;
    public void someMethod() {}
}

我想要求一个实现不仅使用 a,而且还要求它是一个枚举。“标准”方式是通过交叉绑定:MyInterface

static class MyIntersectionClass<T extends Enum<T> & MyInterface> {
    void use(T t) {}
}

但我发现这也有效:

static class MyWildcardClass<T extends Enum<? extends MyInterface>> {
    void use(T t) {}
}

通过上述内容,这将编译:

public static void main(String[] args) throws Exception {
    MyIntersectionClass<MyEnumA> a = new MyIntersectionClass<MyEnumA>();
    a.use(MyEnumA.A);
    MyWildcardClass<MyEnumB> b = new MyWildcardClass<MyEnumB>();
    b.use(MyEnumB.X);
}

对于这两种情况,绑定的工作方式与上述内容的预期和要求相同。

这两个边界之间是否有区别,如果是这样,那么一个边界是否比另一个“更好”?


答案 1

在这种特定情况下没有区别,因为枚举形式类型参数实际上是自类型。这是因为不能像这样从Enum继承:

class MyEnumA extends Enum<MyEnum2> {}
class MyEnumB implements MyInterface {}

所以,是的,从语义上讲,它们是相同的绑定,但只是因为它是Enum。


答案 2

正如其他人所指出的那样,这两种语法实现了相同的界限 - 并且只是因为枚举的特殊情况,我们知道in必须是立即扩展的类型。因此,在限制可以解决的问题时,没有区别。TEnum<T>enumT

的实例的可能用法存在差异,但它可能是一个细微差别,以至于它无关紧要。请考虑以下语句编译为,但不是:TMyIntersectionClass.useMyWildcardClass.use

T t2 = t.getDeclaringClass().newInstance();

只有这些才会在后者中编译:

MyInterface t2 = t.getDeclaringClass().newInstance();
Enum<? extends MyInterface> t3 = t.getDeclaringClass().newInstance();

推荐