通用边界“Enum <t>&amp; Foo”和“Enum <! - ?extends Foo - >”之间是否存在差异</t>

时间:2013-01-02 13:18:02

标签: java generics

这两个(有效的)通用边界是什么:

<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() {}
}

我想要求一个实现不仅使用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);
}

对于这两种情况,绑定对上面的工作和预期都有效。

这两个界限之间是否存在差异,如果是这样的话,并且比另一个“更好”?

4 个答案:

答案 0 :(得分:4)

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

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

所以是的,在语义上他们是相同的界限,但只是因为它是Enum。

答案 1 :(得分:3)

正如其他人所指出的那样,两种语法都达到了相同的界限 - 并且只是因为枚举的特殊情况,我们知道T中的Enum<T>必须是立即延伸的enum }类型。因此,在限制T可以解决的问题时,没有区别。

请考虑以下语句在T但不是MyIntersectionClass.use编译:

MyWildcardClass.use

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

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

答案 2 :(得分:2)

由于第二个依赖于Java枚举被实现为MyEnum extends Enum<MyEnum>的特殊事实,我更倾向于第一个,它不依赖于这样的假设并明确地陈述您的约束。

答案 3 :(得分:1)

他们会做同样的事情,但我会说T extends Enum<? extends MyInterface>更标准,因此更好,只是因为它更常见且可以快速识别。许多人甚至不知道仿制药的&部分。

你也可以说他们的阅读略有不同。 T extends Enum<T> & MyInterface我会将其读作“也恰好是MyInterface的枚举”。 T extends Enum<? extends MyInterface>我会将其读作“实现MyInterface的枚举”。所以在这个程度上,这是个人偏好的问题;我更喜欢后者。