Java方法重载

3
以下方法返回输出:在原始int参数方法中。
  public class TestMethodOverloading {
          private void show(int a){
              System.out.println("in primitive int arg method");
          }
         private void show(float a){
            System.out.println("in primitive float arg method");
          }
         public static void main(String[] args) {
         TestMethodOverloading tmo = new TestMethodOverloading();
         tmo.show(4);
      }
  }

如果我将show方法的参数类型从int更改为Integer,则返回的输出为:在原始浮点数arg方法中。
     public class TestMethodOverloading {
          private void show(Integer a){
                System.out.println("in Integer arg method");
          }
         private void show(float a){
            System.out.println("in primitive float arg method");
          }
         public static void main(String[] args) {
         TestMethodOverloading tmo = new TestMethodOverloading();
         tmo.show(4);
      }
  }

但是,如果我将第二个方法的参数类型从float更改为Float,则输出再次更改为:在Integer arg方法中

      public class TestMethodOverloading {
          private void show(Integer a){
                System.out.println("in Integer arg method");
          }
         private void show(Float a){
            System.out.println("in primitive float arg method");
          }
         public static void main(String[] args) {
         TestMethodOverloading tmo = new TestMethodOverloading();
         tmo.show(4);
      }
  }

有人能帮我理解这种行为吗?

忽略重复的标题,看答案。 - Sotirios Delimanolis
2个回答

7
这是因为在尝试查找匹配的方法以调用时,Java 会先考虑不需要装箱或拆箱转换的方法,然后才会考虑需要装箱或拆箱转换的方法。 JLS 的第 15.12.2 节 指出:
第一阶段(§15.12.2.2)执行重载解析,不允许装箱或拆箱转换,也不允许使用可变元方法调用。如果在此阶段中找不到适用的方法,则处理将继续到第二阶段。
这确保了在Java SE 5.0之前有效的任何调用都不会因为引入可变元方法、隐式装箱和/或拆箱而被视为模棱两可。但是,变量元方法(§8.4.1)的声明可以更改给定方法方法调用表达式所选择的方法,因为在第一阶段中,变量元方法被视为固定元方法。例如,在已经声明m(Object)的类中声明m(Object ...)会导致对于某些调用表达式(如m(null)),不再选择m(Object),因为m(Object [])更具体。
第二阶段(§15.12.2.3)执行重载解析,允许装箱和拆箱,但仍禁止使用可变元方法调用。如果在此阶段中找不到适用的方法,则处理将继续到第三阶段。
这确保了如果通过固定元方法调用适用,则永远不会通过可变元方法调用选择方法。
第三阶段(§15.12.2.4)允许将重载与可变元方法、装箱和拆箱相结合。
(加粗强调是我的)
在第一个示例中,int方法是一个精确匹配,被优先选取而不是float方法,即使它可以在不需要装箱/拆箱的情况下应用。
在第二个示例中,float方法可以在不需要装箱/拆箱的情况下应用,但Integer方法需要装箱,因此选择了float方法。
在第三个示例中,两种方法都需要装箱,所以现在选择了Integer方法。

感谢您的解释.. :) - user3403462

0
在Java方法调用中,扩展转换(int -> float)优先于装箱转换(int -> Integer)。因此,在片段2中,private void show(float a)将被执行,而在片段1中,private void show(Integer a)将被执行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接