通用边界“Enum &Foo”和“Enum “

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

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

一样?


假设我有一个界面

 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 & MyInterface> { void use(T t) {} } 

但我发现这也有效:

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

有了上述,这个编译:

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

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

这两个界限之间是否存在差异,如果是这样,那么一个“比另一个”更“好”吗?

在这种特定情况下没有区别,因为Enumsforms类型参数实际上是自我类型。 这是因为我不能像以下那样从Enuminheritance:

 class MyEnumA extends Enum {} class MyEnumB implements MyInterface {} 

所以是的,从语义上看它们是相同的界限,但仅仅因为它是Enum。

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

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

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

只有这些将在后者编译:

 MyInterface t2 = t.getDeclaringClass().newInstance(); Enum t3 = t.getDeclaringClass().newInstance(); 

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

他们会做同样的事情,但我会说T extends Enum T extends Enum更标准,因此更好,只是因为它更常见和快速识别。 许多人甚至不了解仿制药的部分内容。

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