【问题标题】:Java varargs method overloading compiler error - ambiguity?Java varargs 方法重载编译器错误 - 歧义?
【发布时间】:2017-03-13 09:59:26
【问题描述】:

所以,今天我一直在测试 Java 的重载技术,但遇到了无法解释的歧义。基本上,当有一个原始的可变参数方法及其相应的包装器时,编译器会抱怨并且无法决定选择哪个,我不明白为什么?人类容易决定而不是编译器?

这是适用于非可变参数的片段:

public static void main(String[] args)
{
    int a = 14;
    Integer b = new Integer(14);
    stuff(a);
    stuff(b);
}

static void stuff(Integer arg) { System.out.println("Integer"); }
static void stuff(int arg) { System.out.println("int"); }

来了 vararg 像婴儿一样抱怨和哭泣:

public static void main(String[] args)
{
    int a = 14;
    Integer b = new Integer(14);
    stuff(a); // Doesn't compile (ambiguity)
    stuff(b); // Doesn't compile (ambiguity)
}

static void stuff(int... arg) { System.out.println("varargs int"); }
static void stuff(Integer... arg) { System.out.println("varargs Integer"); }

【问题讨论】:

  • 因为autoboxing,所以实际上这两种方法其实是一样的。
  • 由于自动装箱,Java 知道如果将整数传递给函数,它们可以转换为整数。但是,这意味着这两种方法都是候选方法。作为人类,我们更好,并且知道哪个是最有可能的。
  • 不,抱歉,我认为这还不够。 stuff(int... arg)里面的arg有int[]的类型,那为什么要把参数转换成Integer呢?
  • 看这里以获得更深入的解释:stackoverflow.com/questions/36384527/…

标签: java overloading ambiguity


【解决方案1】:

考虑以下两个对stuff() 的假设调用:

int a = 14;
Integer b = new Integer(14);

stuff(a, b);
stuff(b, a);

编译器怎么知道这里应该调用哪个方法?由于自动装箱规则,任一调用都可能引用任一重载方法。

更新:

我的回答在逻辑上是正确的,或者至少在正确的轨道上,但是对于更正式的答案,我们可以参考这个 SO question:

Why ambiguous error when using varargs overloading with primitive type and wrapper class?

这两个可变参数方法在松散的调用上下文中调用。结果,编译器将尝试通过JLS 15.12.2.5 Choosing the Most Specific Method 找到更具体的方法。但是,由于intInteger 都不是彼此的子类型,因此编译器会抛出错误。

【讨论】:

  • 但是他没有调用带两个参数的方法。虽然在这种情况下肯定会模棱两可,但我认为在这种情况下并不明显。
【解决方案2】:

问题是:

java 在幕后做桥接方法(你需要验证你是否需要深度信息)

重要的部分,vargargs 也意味着你不能传递任何参数,所以:

static void stuff(int... arg)   

static void stuff(Integer... arg) 

两者都可以不带参数地被调用...这样会产生一些关于 JVM 应该调用什么方法的冲突

【讨论】:

  • 嗯,是因为自动装箱还是因为这个,还是这两个原因在这种情况下捆绑在一起?
  • 我创建了两个名为check的方法,一个带有参数String...,另一个带有Integer...,它可以编译(除非我实际上不带参数调用它,否则它不会编译)
  • @Whatzs 如果您也将它们传递给null,它将无法编译。在这种情况下,您需要将null 转换为正确的类型,以告诉编译器您要调用哪个方法:check((Integer) null)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-29
  • 1970-01-01
  • 1970-01-01
  • 2020-08-15
  • 2023-04-09
  • 2023-03-28
  • 1970-01-01
相关资源
最近更新 更多