这两个(有效的)通用边界是什么:
<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);
}
对于这两种情况,绑定对上面的工作和预期都有效。
这两个界限之间是否存在差异,如果是这样的话,并且比另一个“更好”?
答案 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的枚举”。所以在这个程度上,这是个人偏好的问题;我更喜欢后者。