Java:允许具有一个可变参数的函数和具有相同名称和一个相同类型参数的函数吗?

标签 java overloading variadic-functions function-binding

<分区>

在准备 Java 认证考试时,我很惊讶地看到 Java 允许这样做:

public class Consumer {

    public void buy(Object o) {
        System.out.println("Buying one object");
    }

    public void buy(Object... o) {
        System.out.println("Buying multiple objects");
    }

    public static void main(String[] args) {
        Consumer consumer = new Consumer();
        consumer.buy(new Object());
        consumer.buy("a String");
    }

}

这个类可以正常编译和运行。它打印两次“Buying one object”。实际上我想看到一个编译器错误,因为这两个函数都可以使用。编译器如何在这里选择最匹配的函数呢?当我只传递一个参数时,它是否总是选择非可变参数函数?

最佳答案

方法重载解析有 3 个阶段。只有在第 3 个和最后一个阶段,它才考虑带有可变参数的方法(例如您的 public void buy(Object... o)),因此如果在前 2 个阶段之一找到匹配的方法,忽略可变参数方法,选择非可变参数匹配方法。

因此,这两个调用都会导致 public void buy(Object o) 被选中。

Will it always select the non-varargs function when I pass only one argument?

当你只传递一个参数时,它将始终选择非可变参数方法,除非该参数的编译时类型是数组:

Object[] arr = new Object[]{"a string"};
consumer.buy(arr);

传递 null 也会导致编译器选择可变参数方法:

consumer.buy(null);

这是相关的JLS 15.12.2. Compile-Time Step 2: Determine Method Signature引用:

The process of determining applicability begins by determining the potentially applicable methods (§15.12.2.1). Then, to ensure compatibility with the Java programming language prior to Java SE 5.0, the process continues in three phases:

  1. The first phase performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

    This guarantees that any calls that were valid in the Java programming language before Java SE 5.0 are not considered ambiguous as the result of the introduction of variable arity methods, implicit boxing and/or unboxing. However, the declaration of a variable arity method (§8.4.1) can change the method chosen for a given method method invocation expression, because a variable arity method is treated as a fixed arity method in the first phase. For example, declaring m(Object...) in a class which already declares m(Object) causes m(Object) to no longer be chosen for some invocation expressions (such as m(null)), as m(Object[]) is more specific.

  2. The second phase performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.

    This ensures that a method is never chosen through variable arity method invocation if it is applicable through fixed arity method invocation.

  3. The third phase allows overloading to be combined with variable arity methods, boxing, and unboxing.

关于Java:允许具有一个可变参数的函数和具有相同名称和一个相同类型参数的函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48850699/

相关文章:

java - RMI:在特定网络地址和端口上创建服务器

java - 我们可以在 Java trustStore 的逻辑文件夹结构中组织具有多个子项的每个证书链吗

c++ - C++ 中的运算符重载

c++ - C++ 中的模板特化和函数重载

c++ - 模板继承和可变参数

java - 我无法读取用户存储,

java - 在hadoop reducer中执行context.write()时出现空指针异常

typescript - 在 TypeScript 中重载签名必须全部是环境或非环境

c - 在哪里描述了 C 标准可变参数函数?

java - 为什么在 Java varargs (int ...x,double ...y) 中出现这个编译错误?