Java重载:数字,数字;整型,双

2022-09-04 01:25:33

在两天内,我有一个Java考试,我无法弄清楚这个问题的答案:

class ClassA {
 public String foo(Integer x , int y) {
  return "Integer, int";
 }
 public String foo(int x, Double y) {
  return "int, Double";
 }
 public String foo(Number x, Number y) {
  return "Number, Number";
 }
 public String foo(Object x, Object y) {
  return "Object, Object";
 }
 public static void main(String... args) {
  ClassA a = new ClassA();
  System.out.print(a.foo(5, 1.2f) + " ");
  System.out.println(a.foo(null, null));
 }
}

输出是什么?

答案是:

Number, Number Number, Number

我知道java总是选择最指定的方法,这就是为什么会吸引方法而不是方法。但是,为什么也唤起了方法而不是方法??a.foo(null,null);Number,NumberObject,Objecta.foo(5,1.2f);Number,Numberint,Double

但还有一件事可能会有所帮助:如果我删除之后,那么调用是:我得到一个编译器错误,它不能在和方法之间进行选择...f1.2a.foo(5,1.2);Number,Numberint,Double

如果你们能向我解释这一点,那将真的很有帮助,:)


答案 1

1.2f不是由 a 包装的,而是由 .由于 不是 的子类(它们是 的不同子类),因此可以使用的最具体的方法签名是 。DoubleFloatFloatDoubleNumberfoo(Number,Number)

一旦你删除了 ,1.2 将被视为默认的(原语,而不是包装类),它可以自动装箱到 .然而,5 也可以自动装箱为 ,从而导致歧义。fdoubleDoubleInteger


答案 2

这里有两个重要因素。

首先,不是 .这是一个.该函数完全不匹配。 是最适合的。1.2fDoubleFloat(int, Double)(Number, Number)

其次,即使你把它改成它仍然不是一个.这是一个.也就是说,它是一个基元,而不是一个对象。现在,Java仍然会很乐意将a传递到一个想要a的函数中,而没有太多的抱怨,但是在这种情况下,你通过给它两个有效的转换来混淆它:1.2DoubledoubledoubleDouble

  1. 转换为 和 转换为5Integer1.2Double
  2. 保留为基元,但转换为 .5int1.2Double

没有规则规定其中哪一个更可取。Java 会产生一个编译器错误,指出它具有不明确的函数调用,并强制您选择自己喜欢的函数调用(通过手动将其中一个或两个包装在对象中)。

顺便说一句,如果你有一个方法,那么根本就不会有歧义:该方法实际上与现有的类型和匹配,因此它将被调用。事实上,这里的一些参数是导致混乱的包装器对象。(int, double)51.2