Java最具体的方法子类型规则

时间:2016-12-22 23:21:14

标签: java language-lawyer jls

在Java语言规范的§15.12.2.5中,他们描述了Java如何从可访问的适用的方法的列表中选择最具体的方法来调用。< / p>

有一条我不明白的具体评论,即:

  

(1)对于任何表达式,类型 S 更具体而不是类型 T   如果 S&lt;:T

真正困扰我的部分是“any expression”

为了给出一个例子,我将引用上一段说明当给出两个方法m 1 和m 2 时我们可以说m 1对于带参数表达式e 1 ,...,e k <的调用, 更具体而不是m 2 / sub> if:

  

m 2 不是通用的,m 1 和m 2 适用于严格或宽松   调用,其中m 1 具有形式参数类型S 1 ,...,S n 和m 2   有形式参数类型T 1 ,...,T n ,类型S i 更具体   对于所有i(1≤i≤n,n = k),参数e i 比T i

因此,如果类型S i (m 1 )比T i 更具体(m 2 )对于所有i,使用参数表达式e i ,然后m 1 更具体而不是m 2

现在考虑一下:

int a(Number a) { return 1; } // m1
int a(Double a) { return 2; } // m2

Double <: Number开始,因为任何表达式Double都比Number更具体(来自引用1)。

我们有:

m 1 :S 1 =&gt;编号

m 2 :T 1 =&gt;双重

但是如果我们的参数参数表达式e 1 的类型为Number m 2 是最具体的方法,因为Double是最具体的对于任何表达式(引用1)。

但是,如果我们将Number传递给a(),则结果为1即。未选择采用Double的方法。但引用1表示如果DoubleNumber的子类型,任何表达式Double都会更具体,那么它如何选择a(Number)

我在这里缺少什么?

注意: 我知道Number不能分配给Double,编译器选择另一个是没有意义的,我只是想看看我从第一个引文中误解的是什么

1 个答案:

答案 0 :(得分:0)

事实证明我的误解不是引用的一部分,而是适用功能在松散严格调用下的内容

更具体地说, strict / loose 调用上下文允许一组转换

  • 身份转换即。 NumberNumber
  • 拓宽原始转换即。 byte to short,int,long,float or double
  • 扩大参考转换即。 DoubleNumber
  • 拳击转换即。 int to Integer可选地后跟扩展的引用转换
  • 拆箱转换即。 Integer to int可选地后跟扩展的原始转换

在我的示例中,我忽略了扩展引用转换无法应用于Number的事实,因为Number不是Double的子类型,因此{ {1}}不被视为适用的方法。