【问题标题】:Java Method Overloading with Boxing/Widening带有装箱/加宽的 Java 方法重载
【发布时间】:2013-03-19 06:57:35
【问题描述】:

我正在研究 Java Se 7 OCA,但无法弄清楚为什么下面的代码无法编译。 main 方法中的 aMethod 调用给出了编译错误,说明方法不明确。在这个重载方法示例中,加宽和装箱之间的优先规则似乎发生冲突。

public class Overloading {
public static void main(String[] args) {
    Byte i = 5;
    byte k = 5;
    aMethod(i, k);
}

static void aMethod(byte i, Byte k) {
    System.out.println("Inside 1");
}

static void aMethod(byte i, int k) {
    System.out.println("Inside 2");
}

static void aMethod(Byte i, Byte k) {
    System.out.println("Inside 3 ");
}
}

错误是“方法 aMethod(byte, Byte) 对于类型 Overloading 不明确”。 当我注释掉第一种方法时,第二种方法会出现同样的错误。

我的想法是: 第一种方法需要拆箱和装箱 第二种方法需要拆箱和加宽 第三种方法只需要拳击。 所以它必须是第三种方法,因为它需要的转换最少,而且都是拳击转换。

【问题讨论】:

  • 错误信息是?
  • 为什么你认为这个应该编译?
  • 您可以在这里找到问题的正确解释:stackoverflow.com/a/4921807/1065197。由于编译器将进入第 3 阶段,它会发现不止一个合适的方法来使用,因此是模棱两可的。

标签: java overloading scjp


【解决方案1】:

问题在于所有这些方法:

static void aMethod(byte i, Byte k) {
    System.out.println("Inside 1");
}

static void aMethod(byte i, int k) {
    System.out.println("Inside 2");
}

static void aMethod(Byte i, Byte k) {
    System.out.println("Inside 3 ");
}

Java 不知道,它应该直接调用哪一个:

    aMethod(i, k);

你的参数ik可以通过多种方式转换,根据JLS 规范:

i 可以是 unboxedbyte (5.1.8) 或保留为 Byte (5.1.1) -> 2 个变体

k 可以是 boxedByte (5.1.7) 或扩大到 int 类型 (5.1.2) -> 2 个变体。

【讨论】:

  • 你是对的;但转换有优先规则。它将选择扩大而不是拳击。并且它必须在适当的时候将“i”保留为字节而不是拆箱。
  • @isaolmez 唯一可以在此处使用的优先级是规则 5.1.1(将类型转换为相同类型)。如果您没有使用适当签名的方法(即aMethod(Byte i, byte k)),则此优先级没有意义。
【解决方案2】:

这个类你有两个相等的方法

static void aMethod(Byte i, Byte k) {
    System.out.println("Inside 3 ");
}

static void aMethod(byte i, Byte k) {
    System.out.println("Inside 1");
}

字节自动转换字节,所以编译出错

【讨论】:

  • 其实我的调用是模棱两可的,方法没问题。
【解决方案3】:

其实不是定义,而是叫法有歧义。 因为,默认情况下java中的所有整数都是int。即使您说 byte b =5,对于任何操作,5 都会在内部转换为 int。但由于引用是字节,在你的情况下,它可以选择调用方法 2 和 3。所以编译器无法理解要调用什么。

所以aMethod(i, (Byte)k) 应该可以工作。

【讨论】:

  • 我假设您建议使用 aMethod(i, (int)k)。但在这种情况下,此调用没有其他选项。只有整数接受方法是第二种。
  • 不要假设。正如我所说,默认情况下,所有整数文字都转换为 int,无论是短、字节还是长。所以通过参考编译器看到字节,但从值它看到一个int。那就是产生歧义。所以在这里, aMethod(i, (byte)k) 可以工作,否则你可能需要传递一个 int 类型的值。这可以通过调用 aMethod(i, 5) 和 aMethod(i, (byte)5); 来验证;
  • aMethod(i, (byte)5);没有编译并给出了同样的错误。但如果我使用 aMethod(i, 5),它会编译。
  • 哎呀....我写了(字节)k....应该是(字节)k。因为显式转换和自动装箱是相互排斥的。
【解决方案4】:

在 Java 中方法重载时应牢记以下几点:

  1. 原始类型的扩展使用紧邻的下一个更广泛的类型 方法参数,如果没有找到完全匹配。

  2. 装箱和可变参数与方法重载兼容,如果它们 单独使用。

  3. 一种包装类型不能扩展到另一种。例如,整数 不能扩大到 Long。

  4. 加宽后装箱不起作用。例如,一个 int 不能 传递给 Long。

  5. 装箱后加宽仅在一种情况下有效 参数被传递给对象类型引用。可以传递一个 int 到一个对象,通过整数。

  6. Var-args 可以与加宽或装箱结合使用,但 小心点。

在上面的代码中,传递给 aMethod 的参数应该进行适当的类型转换,因为 Java 中的中间结果在 int 表达式中转换为 int。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-26
    • 1970-01-01
    • 2015-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多