【问题标题】:Java Primitive Widening Interview [duplicate]Java Primitive Widening 访谈 [重复]
【发布时间】:2016-04-17 13:45:40
【问题描述】:

你能解释一下为什么结果是“int”吗?如果变量是一个字节,我希望它是“长的”。

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);
      }
}

【问题讨论】:

    标签: java


    【解决方案1】:

    您好,结果是“int”,因为在运行主函数时,您没有 printValue 使用一个参数,而是使用 3 个参数。所以编译器假定您指的是具有 3 个参数的第一个 printValue。由于您没有在函数内使用这些参数,因此一切正常,没有任何运行时错误。另一方面,我会说以这种方式查找变量的类型并不是一个好习惯。最好的方法是使用“if else”语句。你可以参考这篇文章来了解如何在 java 中找到类型:How do you know a variable type in java?

    【讨论】:

      【解决方案2】:

      Java 编译器必须在两种匹配方法之间进行选择。它总是会选择一种不使用可变参数(varargs)的方法而不是使用它的方法。它宁愿将所有 3 个参数提升到 int 以匹配第一个 printValue 而不是使用可变参数。

      Section 15.12.2 of the JLS 状态:

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

      1. 第一阶段(第 15.12.2.2 节)执行重载解决方案,不允许装箱或拆箱转换,或使用可变参数方法调用。如果在此阶段未找到适用的方法,则处理继续到第二阶段。

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

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

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

      1. 第三阶段(第 15.12.2.4 节)允许将重载与可变数量方法、装箱和拆箱结合使用。

      (我的粗体强调)

      在第一阶段找到匹配方法(第一个重载),因此编译器甚至不考虑第三阶段 - 允许可变的arity方法 - 所以打印int

      选择第二个重载(与直觉相反地打印long)的一种方法是显式创建一个数组,以便第一个重载无法匹配。

      printValue(new byte[]{b,b,b});
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-07-25
        • 2012-05-09
        • 1970-01-01
        • 2020-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多