【问题标题】:Why does type-promotion take precedence over varargs for overloaded methods为什么类型提升优先于重载方法的可变参数
【发布时间】:2015-06-01 12:29:38
【问题描述】:
public class Test
{
    public static void printValue(int i, int j, int k)
    {
        System.out.println("int");
    }

    public static void printValue(byte...b)
    {
        System.out.println("long");
    }

    public static void main(String... args)
    {
        byte b = 9;
        printValue(b,b,b);
    }
}

上述代码的输出是“int”。但它应该是“长”的,因为字节类型参数函数已经存在。但是这里程序将字节值提升为int,但事实并非如此。

请有人解释一下这里发生了什么?

【问题讨论】:

  • 请阅读有关在帖子中包含代码的文档,并在发布之前使用预览检查它是否合理。

标签: java overloading variadic-functions


【解决方案1】:

JLS 15.12.2 是要在此处查看的规范的相关位。特别是 - 强调我的:

流程的其余部分分为三个阶段,以确保与 Java SE 5.0 之前的 Java 编程语言版本兼容。阶段是:

  • 第一阶段(第 15.12.2.2 节)执行重载决议,不允许装箱或拆箱转换,或使用变量 arity 方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段。

    这保证了在 Java SE 5.0 之前的 Java 编程语言中有效的任何调用都不会因为引入可变数量方法、隐式装箱和/或拆箱而被视为模棱两可。 em> 但是,变量 arity 方法的声明(第 8.4.1 节)可以更改为给定方法方法调用表达式选择的方法,因为变量 arity 方法在第一阶段被视为固定 arity 方法.例如,在已经声明 m(Object) 的类中声明 m(Object...) 会导致不再为某些调用表达式(例如 m(null))选择 m(Object),因为 m(Object[]) 更具体。

  • 第二阶段(第 15.12.2.3 节)在允许装箱和拆箱的同时执行重载解决方案,但仍排除使用变量 arity 方法调用。如果在此阶段没有找到适用的方法,则处理继续到第三阶段。

    这确保了一个方法永远不会通过可变的方法调用来选择,如果它适用于通过固定的方法调用。

  • 第三阶段(第 15.12.2.4 节)允许将重载与可变参数方法、装箱和拆箱相结合。

在您的情况下,第一阶段在不使用变量 arity 方法调用或装箱的情况下找到匹配项,因此这就是结果。如规范中所述,这基本上是为了向后兼容。

【讨论】:

  • 非常感谢乔恩。它澄清了我的疑问。但是,我无法进入第三阶段。
  • @ShipraVarshney 你可以看看我的答案,以便更简单地理解。
  • @ShipraVarshney:基本上是“尝试在不使用拳击或可变参数的情况下找到匹配项。然后尝试使用拳击而不是可变参数来找到匹配项。然后尝试使用拳击和可变参数找到匹配项。”
【解决方案2】:

在重载方法的情况下,可变参数方法将始终是编译器选择的最后一个。将byte 提升为int(加宽转换)将优于采用 var-arg 参数的方法。

这背后的原因是语言需要向后兼容。旧功能将优先于新功能。理解JLS 关于可变参数的一个简单方法是,加宽将击败拳击,而拳击将击败 var-args。

【讨论】:

    猜你喜欢
    • 2012-04-15
    • 1970-01-01
    • 2021-08-15
    • 2015-03-30
    • 2019-05-22
    • 2019-10-22
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    相关资源
    最近更新 更多