【问题标题】:Passing byte arguments to overloaded method将字节参数传递给重载方法
【发布时间】:2020-03-12 20:49:29
【问题描述】:

我从一些测验中获取了这段代码 sn-p,使用 IDE 我执行它并得到结果 long, long 但正确答案是 Byte, Byte,为什么我得到了不同的结果?该问题与JDK 11有关

public class Client {
    static void doCalc(byte... a) {
        System.out.print("byte...");
    }

    static void doCalc(long a, long b) {
        System.out.print("long, long");
    }

    static void doCalc(Byte s1, Byte s2) {
        System.out.print("Byte, Byte");
    }

    public static void main(String[] args) {
        byte b = 5;
        doCalc(b, b);
    }
}

已编辑:

代码取自这里:Oracle Certification Overview and Sample Questions (第 13 页,问题:5)

【问题讨论】:

标签: java


【解决方案1】:

所以,如果你在编译时通过 Java 语言 specification 来确定方法签名,那就很清楚了:

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

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

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

因此,从上述步骤中,很明显,在您的情况下,在 第一阶段,Java 编译器将找到一个匹配方法,它执行 doCalc(long a,long b)。您的方法doCalc(Byte s1, Byte s2) 在调用期间需要自动装箱,因此它的偏好会降低。

【讨论】:

  • 关于为什么long 接受byte,似乎遵循扩大原始转换docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.2。所以基本上,+widening -boxing -varargs 然后+widening +boxing -varargs 然后+widening +boxing +varargs
  • @kbo 为什么你认为正确答案是Byte, Byte
  • @kbo 我猜 正确答案 不正确 :) 如果可以的话,可能值得向作者指出这个问题。
  • @sp00m 我在 Oracle 的示例中发现了这个问题,请查看编辑部分
  • @kbo 哇...不知道如何继续!
【解决方案2】:

请阅读JLS chapter on conversions

在您的情况下发生的情况是,在运行时,JVM 选择执行 加宽转换 byte -> long,因为这种转换更安全,因为它保证不会导致 RuntimeException

byte 转换为Byte 也称为装箱 可能导致OutOfMemoryError,因为JVM 必须将新对象分配到堆上:

如果需要分配包装类(Boolean、Byte、Character、Short、Integer、Long、Float 或 Double)之一的新实例并且可用的存储空间不足,则装箱转换可能会导致 OutOfMemoryError。

因此,更安全的byte -> long扩大转化率是首选。

【讨论】:

  • 请注意,从byteByte 的装箱永远不会导致OutOfMemoryException,因为Byte (-128 - 127) 的所有值都在内部缓存。但它可能与其他类型不一样,因此根据经验,扩大转换优先。
【解决方案3】:

为了找到正确的重载,顺序是:

  1. 按参数数量
  2. 装箱/拆箱
  3. 可变参数

所以

  • 如果bByte,则结果将为Byte, Byte
  • 如果通过将是new byte[] { b, b },结果将是byte, byte
  • 如果传递两个字节 b,加宽从 byte 到 int 到 long 是可能的,结果是long, long
  • 当 long、long 重载被移除时,Byte, Byte 结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 1970-01-01
    • 2011-07-23
    • 2017-01-05
    • 2013-10-04
    • 2013-05-19
    • 2013-02-08
    相关资源
    最近更新 更多