尽管Java没有泛型[@ runtime],但最近我还陷入了某种通用的地狱。
情况(已删除简化和无用的上下文):
有一个库A,它提供了一个接口IA。有一个库B,它提供了一个接口IB。这两个库都是第三方库,我完全无法控制它们。 (实际上,有两个以上,但不要让它过于复杂。)
我的公司开发了一种引擎,它既定义又大量使用IA / IB的对象。因为我们的引擎必须处理所有实现,所以我们不能简单地定义一些interface IAB implements IA, IB
并让我们所有的类实现它。因此,为了实现编译时类型安全&方法曝光,决定使用通用方法。因此,每当需要'IAB'时,我们就会有
<IAB extends IA & IB> void doThis(IAB someObjectWithBothAPIs)
。
事实上,这非常有效。但是,不可能像<IAB extends IA & IB> IAB fieldWithBothAPIs;
那样简单(IA & IB fieldWithBothAPIs;
)。这带来了我们的问题:
为什么不呢?
基本上,允许任意TypeParams(opt)
的(设计级别?)原因是什么,而实例字段仅限于具体Type
?
JLS§8.3
FieldDeclaration:
FieldModifiers(opt) Type VariableDeclarators ;
JLS§8.4
MethodDeclaration:
MethodHeader MethodBody
MethodHeader:
MethodModifiers(opt) TypeParameters(opt) Result MethodDeclarator Throws(opt)
答案 0 :(得分:1)
泛型方法在运行时从其调用上下文接收其类型参数。它可以在不同的情况下接收不同的类型。
通用字段如何接收类型参数?根据在某些情况下的使用,该字段不能具有不同的类型。它必须具有单一类型,在编译时已知。
答案 1 :(得分:1)
你可以这样做,而不是在宣言中。
interface IA {}
interface IB {}
interface IC {}
class Generic<IAB extends IA & IB> {
final IAB iab;
Generic(IAB iab) {
this.iab = iab;
}
<IBC extends IB & IC> void method(IBC arg) {
IBC ibc = arg;
}
}
避免在每一行上执行此操作的一个很好的理由是,扩展相同内容的两种类型可能不一样。
例如,你可以写的图像
class Generic {
<IAB extends IA & IB> IAB iab;
<IBA extends IA & IB> IBA iba;
<IAB extends IA & IB> void method(IAB arg) {
iab = arg; // error, types are not the same.
iba = iab; // compile error as the types are not the same.
与此相同,语法正确且无法编译。
class Generic<IAB extends IA & IB, IBA extends IA & IB> {
IAB iab;
IBA iba;
<IAB extends IA & IB> void method(IAB arg) {
iab = arg; // error, types are not the same.
iba = iab; // compile error as the types are not the same.