方法调用对变量操作符有歧义



下面的代码会产生语法错误:

对于C

类型,方法f(int[])是不明确的
我代码:

public class C{
    public static void f(int... i)
    {
        System.out.println("a");
    }
    public static void f(Integer... i)
    {
        System.out.println("b");
    }
    public static void main(String[] args) {
        f(new Integer(2));
    }
}

如果我用数组符号[]代替...,并且用f(new Integer[]{3,4,5})正确地调用函数,编译器可以正确地决定我要使用哪个方法。

编译器不能决定用...调用哪个函数的原因是什么?

查找"正确"的过程;在JLS第15.12节"方法调用表达式"中解释了用于特定调用站点的方法。在进行基本的完整性检查之后,相关部分从15.12.2.1节,识别潜在的适用方法开始。在您的情况下,根据这个定义,两个方法都可能适用

后续过程包括三个阶段。在您的例子中,该方法是一个变量方法(由于&;varargs")。因此,它立即从15.12.2.4开始,阶段3:确定适用的可变密度方法。

方法m是一个适用的变量方法,当且仅当满足以下所有条件:

  • 对于1≤i

(其他条件在这里不相关)

方法调用转换(JLS, 5.3)允许以下转换:

  • 标识转换(§5.1.1)
  • 一个扩展的原语转换(§5.1.2)
  • 扩大参考转换(§5.1.5)
  • 一个装箱转换(§5.1.7)可选地跟随扩展引用转换
  • 一个可选的拆箱转换(§5.1.8),后跟一个扩展原语转换。

IntegerInteger的转换是标识转换(第一个要点)。从Integerint的转换是一个开箱转换(最后一个要点)。

所以这两种方法都是"适用变量方法"。

VarargsBoxing都是在Java 5以后引入的。在Java 5中出现了处理遗留代码的问题,其中编译器执行扩展操作(例如,在有long的地方,编译器将选择long而不是Integer,因为在Java 5之前允许从int扩展到long的操作),但是由于varargs和Boxing处于同一级别(Java 5起),编译器无法确定正确的类型。只需删除变量并用数组替换,就可以了

当Varargs和装箱/拆箱组合使用时,它们之间没有定义的优先级

规则是WBV/WAV 方法重载的情况下,拓宽->(自动)装箱-> Varargs

  1. 扩大
    int -> long -> float -> double
    
  2. 拳击
    Integer -> Number -> Object
    
  3. a)扩大然后Varargs

    int... -> long... -> float... -> double...
    

    b)将Varargs装箱

    Integer... -> Number... -> Object...
    

换句话说

   Varargs  [Last option]
      ^
      |
   Boxing   [Newer style, added in Java 1.5]
      ^
      |
   Widening [Older style, choosen by the compiler to support existing code]

注意:

  • BoxingWidening也可以。
  • Varargs则不允许Boxing
  • Varargs被视为Wideningboxing之间的最后一个选项
  • 选择Widening then VarargsBoxing then Varargs。如果这两种可能性都存在,则会导致歧义的方法调用。

f(new Integer(2))的情况下的转换。根据Boxing规则,Widening

Integer -> Number -> Object -> int -> long -> float -> double

现在double旁边有两种可能性

  • 3.a)拉大Varargs (int...)

  • 3.b) Boxing then Varargs (Integer...)

但是两者都存在,因此导致歧义的方法调用。


f(new Integer[]{3,4,5})

的转换

Integer...是直接匹配。Varargs then Boxing不允许

…用于可变数量的参数。你必须传递像f(1,2,3)这样的值,这就是错误的原因。

最新更新