【问题标题】:Java most specific method subtyping rulesJava 最具体的方法子类型化规则
【发布时间】:2016-12-22 23:21:13
【问题描述】:

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

有一个具体的说法我不明白,即:

(1) 对于任何表达式,类型 S 比类型 T 更具体 如果 S <: t>

真正困扰我的部分是“任何表达”

举个例子,我将引用上一段,当给定两个方法 m1 和 m2 我们可以说 m1对于带有参数表达式 e1, ..., ek 比 m2 更具体 /sub> 如果:

m2 不是泛型的,m1 和 m2 可以通过严格或宽松来适用 调用,其中 m1 具有形式参数类型 S1、...、Sn 和 m2 有形参类型 T1, ..., Tn,类型 Si 更具体 比 Ti 为参数 ei 为所有 i (1 ≤ i ≤ n, n = k)。

所以如果类型 Si (m1) 比 Ti (m2 ) 对于所有 i,参数表达式为 ei,则 m1 比 m2

更具体 >

现在考虑一下:

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

由于Double &lt;: Number,因此对于任何表达式Double 都比Number 更具体(来自引用1)。

我们有:

m1 : S1 => 数字

m2 : T1 => 双倍

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

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

我在这里错过了什么?

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

【问题讨论】:

  • 这让我很困惑。您已经引用了“and applicable”,然后您想知道为什么不选择具有不适用参数类型的方法,即使它具有更具体的类型并且会被使用 如果适用吗?什么? a(Double) 不使用 Number,这里没什么好说的了。
  • @Tom 天哪。当基本前提是错误的时,我经历了所有试图理解这一点的麻烦。我认为它始终适用。非常感谢!
  • 您可以用其他类型重新考虑这些规则,例如 DoubleIntegernull(只是为了它的见鬼 :D)。也许还有一些原语。这可能很有趣。
  • 恕我直言,更重要的是决定是在编译时做出的,而不是在运行时。
  • @Tom 是的,我会的,我只是误解了引用扩展并认为它是适用的,只是因为它们位于同一继承树上

标签: java language-lawyer jls


【解决方案1】:

事实证明,我的误解不是引用的一部分,而是关于 applicable 函数在 loosestrict 调用下的含义.

更具体地说,严格/松散调用上下文允许一组转换

  • 身份转换,即。 NumberNumber
  • 扩大的原始转换即。 byte to short,int,long,float or double
  • 扩大参考转换即。 DoubleNumber
  • 拳击转换即。 int to Integer 可选地后跟扩大的参考转换
  • 拆箱转换,即。 Integer to int 可选地后跟一个扩大的基元转换

在我的示例中,我忽略了以下事实:扩大引用转换不能应用于 Number,因为 Number 不是 Double 的子类型,因此 int a(Double a) 不被视为适用方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-10
    • 1970-01-01
    • 2012-03-10
    • 2020-02-24
    相关资源
    最近更新 更多