java中的重载方法优先级 [英] overloading method priority in java

查看:259
本文介绍了java中的重载方法优先级的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这个问题讨论了很多次,但我还是不明白。

I know that this problem discussed many times but I don't understand anyway.

研究这段代码:

public class Main {  
    public static void var(Integer x, int y) {  
        System.out.println("Integer int");  
    }  


    public static void var(int... x) {  
        System.out.println("int... x");  
    }  

    public static void var(Integer... x) {  
        System.out.println("Integer...");  
    }  

    public static void main(String... args) {   
        byte i = 0;  
        Integer i2 = 127;  
        var(i, i2);  
    }  
} 

在我的大脑遵循规则:


  1. 加宽

  1. widening

拳击

拳击+ varargs

boxing+varargs

根据此规则我会做出下一步行动

According this rule I make next actions

1.byte wides to int

1.byte wides to int

现在我有 int 整数并且存在方法需要整数 int

Now I have int Integer and there are exist method takes Integer and int

2.make boxing

2.make boxing

因此。 int - > 整数整数 - > int 参数

Hence. int -> Integer and Integer -> int arguments

我认为参数适用且预计会看到

I think that arguments are applicable and expected to see

Integer int

但是我看到了

int ...

为什么?

推荐答案

现在很清楚,方法 var(int ...)被选中,而不是 var(整数......)

It is now clear that the method var(int...) is selected and not var(Integer...).

原因是只允许应用某些转化,并且它只能是列表中的转化之一,而不是转化链。
首先不允许java编译器进行扩展原始转换,然后进行装箱转换。

The reason is that only certain conversions are allowed to be applied, and it can only be one of these conversions from the list, not a chain of conversions. The java compiler is not allowed to do a widening primitive conversion first, and then a boxing conversion.

它在第5.3节中的Java语言规范


5.3。方法调用转换

5.3. Method Invocation Conversion

方法调用转换应用于
方法或构造函数调用中的每个参数值(§8.8.7.1,§15.9,§15.12):必须将参数表达式的
类型转换为
对应参数的类型。

Method invocation conversion is applied to each argument value in a method or constructor invocation (§8.8.7.1, §15.9, §15.12): the type of the argument expression must be converted to the type of the corresponding parameter.

方法调用上下文允许使用_ 其中一个 _以下内容:

Method invocation contexts allow the use of _one of_ the following:


  • 身份转换(第5.1.1节)

  • 扩大原始转换(§5.1.2)

  • 扩大参考转换(§5.1.5)

  • 一个拳击转换(§5.1.7)可选地后面加宽引用
    转换

  • 一个拆箱转换(§5.1.8),可选地后跟一个加宽的
    原始转换。

  • an identity conversion (§5.1.1)
  • a widening primitive conversion (§5.1.2)
  • a widening reference conversion (§5.1.5)
  • a boxing conversion (§5.1.7) optionally followed by widening reference conversion
  • an unboxing conversion (§5.1.8) optionally followed by a widening primitive conversion.

编译器的唯一选择是:


  1. 第一个参数的扩展原始转换

  2. 第二个参数的拆箱转换

转为(字节,整数)进入(int,int)

它不能先将第一个参数 byte 转换为 int 然后对来自 int 的相同参数应用装箱转换为 Integer ,因为不允许按顺序进行两次转换。

It cannot first turn the first argument byte into an int and then apply a boxing conversion on the same argument from int to Integer because two conversions in sequence are not allowed.

让我们回过头来了解编译器如何选择要调用的重载方法。这在 JLS 15.12中有所描述。 2 。 (15.12.1描述了如何找到要搜索的类或接口,但我们已经知道我们想在类 Main 中调用静态方法)

Let's go back one step to find out how the compiler selects which overloaded method to invoke. That is described in JLS 15.12.2. (15.12.1 describes how to find the class or interface to search, but we already know that we want to invoke a static method in class Main)

编译器选择正确重载方法的前两个阶段不适用于变量参数(变量arity)方法,但第三阶段确实如此:

The first two phases that a compiler goes through to select the right overloaded methoddo not apply to variable argument ("variable arity") methods, but the third phase does:


第三阶段(§15.12.2.4)允许重载与
变量arity方法,装箱和拆箱相结合。

The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.

第15.12.4节非常复杂,但适用的规则是:

Section 15.12.4 is quite complicated, but the rules that apply here are:


  • 首先应用非变量arity参数的规则(在您的情况下不适用)

  • 调用中的每个变量参数必须可通过方法调用转换转换
  • (我上面复制的那篇)到变量参数声明的类型
  • first apply the rules for non-variable arity arguments (not applicable in your case)
  • each variable argument in the invocation must be convertable by method invocation conversion (the piece that I copied above) to the type of the variable argument declaration

所以......


  1. 你试试o使用(字节,整数)调用名为 var 的方法

  2. 编译器查看你的方法 var(整数...)

  3. 它问:我可以转换第一个参数,一个 byte ,到 Integer (方法中声明的参数类型)

  4. it查看JLS 5.3中的规则。它只能应用5个列表中的一个转换。它们都不能将字节转换为整数直接 - 它不能做两个步骤。

  5. 因此编译器决定它不能选择 var(整数......)

  6. 然后它会查看你的另一种方法, var(int ...)

  7. 根据JLS 5.3,它可以使用扩展原语转换将你的第一个参数 byte 转换为 int 。这是一个复选标记。

  8. 继续第二个参数,你的 Integer ,它看到JLS 5.3允许编译器转换它使用拆箱转换 int 。所以这也是一个复选标记。

  9. 这是最后一个参数,所以 var(int ...)是一个很好的匹配。

  10. 编译器现在继续查看是否有更多方法与您的调用相匹配。如果还有更多,那将导致模糊调用错误。

  11. 但是没有更多名称为 var ,所以 var(int ...)是唯一适用的方法。编译器现在将生成代码以执行必要的转换并调用该方法。

  1. you try to invoke a method named var with (byte, Integer)
  2. the compiler looks at your method var(Integer...)
  3. it asks: can I convert the first argument, a byte, to Integer (the declared type of the argument in the method)
  4. it looks at the rules in JLS 5.3. It can only apply one of the conversions from the list of 5. None of them can convert a byte to an Integer directly - it cannot do two steps.
  5. So the compiler decides that it cannot select var(Integer...)
  6. then it looks at your other method, var(int...)
  7. According to JLS 5.3, it can convert your first argument, the byte to an int using a widening primitive conversion. That's a check mark.
  8. Moving on to the second argument, your Integer, it sees that JLS 5.3 allows the compiler to convert it to an int using an unboxing conversion. So that's also a check mark.
  9. That was the last argument, so var(int...) is a good match.
  10. The compiler now moves on to see if there are more methods that match your invocation. If there are more that do, that will result in an ambiguous-invocation error.
  11. But there are no more methods with the name var, so var(int...) is the only applicable method. The compiler will now generate code to do the necessary conversions and invoke that method.

这篇关于java中的重载方法优先级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆