Java:为什么用户必须满足扩展约束?

时间:2016-02-26 05:00:20

标签: java types type-theory

考虑以下代码:

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;在这份声明中可以证明吗?为什么类型系统是这样设计的?

1 个答案:

答案 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编译器在看到它时拒绝不可能。