考虑以下代码:
public class Enclosing {
class A<X extends Y, Y> {}
<U, V> void foo(A<U,V> a) {}
}
这给了我一个错误:
类型参数U不在其范围内;应该扩展V。
但是,除非你可以构造一个A的实例,否则调用这个函数应该是不可能的,那么为什么foo的声明需要确保U在它的范围内呢?我知道你可以通过传递null
来违反这一点,但我的直觉是,健全性仍然只需要&#34; U延伸V&#34;当A被构造时,约束是可证明的,而不是在它被使用时。
那么,为什么Java要求&#34; U扩展V&#34;在这份声明中可以证明吗?为什么类型系统是这样设计的?
答案 0 :(得分:3)
尽管允许<U, V> void foo(A<U,V> a)
无害,因为如果U没有扩展V,你永远不会构造a
的实例(尽管如你所说,你可以有效地通过null
),对于编译器来说,如果不标记逻辑不可能,它就没有用了。
如果您显示,参数a
的类型是逻辑上不可能的。类型为A
,类型参数为U和V,其中U不限于V的子类型。我们不能说这种类型A,因为它们只存在类型A,它是第一类型参数的类型A 被约束为第二个类型参数的子类型。
如果您按照建议允许声明,则还应允许此声明:
void foo(A<String,Integer> a);
因为在你的推理中,“健全性仍然只需要在构造A时证明”String extends Integer“约束,而不是在使用它时。”
这可能是一种解决方法,但我认为大多数人都希望Java编译器在看到它时拒绝不可能。