Java:允许具有一个可变参数的函数和具有相同名称和一个相同类型参数的函数吗? [英] Java: Function with one varargs argument and function with same name and one argument of same type is allowed?

查看:69
本文介绍了Java:允许具有一个可变参数的函数和具有相同名称和一个相同类型参数的函数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

While preparing for Java certification exam I was quite surprised to see that Java allows this:

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");
    }

}

这个类编译并运行良好.它打印了两次购买一个对象".实际上我以为会看到编译器错误,因为这两个函数都可以使用.这里编译器是如何选择最佳匹配函数的?当我只传递一个参数时,它是否总是选择非可变参数函数?

This class compiles and runs fine. It prints "Buying one object" two times. Actually I thought to see a compiler error because both functions could be used. How does the compiler select the best matching function here? Will it always select the non-varargs function when I pass only one argument?

推荐答案

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

Method overloading resolution has 3 stages. Only on the 3rd and last stage it considers methods with varags (such as your public void buy(Object... o)), so if a matching method is found in one of the first 2 stages, the varargs methods are ignored, and the non-varag matching method is chosen.

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

Therefore both calls result in public void buy(Object o) being chosen.

当我只传递一个参数时,它是否总是选择非可变参数函数?

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

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

It will always select the non-varargs method when you pass only one argument, unless the compile time type of that argument is an array:

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

传递null也会导致编译器选择varargs方法:

Passing null will also cause the compiler to select the varargs method:

consumer.buy(null);

这是相关的JLS 15.12.2.编译时第 2 步:确定方法签名 引用:

Here's the relevant JLS 15.12.2. Compile-Time Step 2: Determine Method Signature quote:

确定适用性的过程始于确定潜在适用的方法(第 15.12.2.1 节).然后,为确保与 Java SE 5.0 之前的 Java 编程语言兼容,该过程将分三个阶段继续:

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. 第一阶段执行重载解析不允许装箱或拆箱转换,或使用可变数量方法调用.如果在此阶段找不到适用的方法,则处理继续到第二阶段.

  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.

这保证了在 Java SE 5.0 之前的 Java 编程语言中有效的任何调用都不会因为引入可变数量方法、隐式装箱和/或拆箱而被认为是模棱两可的.但是,变量 arity 方法(第 8.4.1 节)的声明可以更改为给定方法方法调用表达式选择的方法,因为在第一阶段,变量 arity 方法被视为固定的 arity 方法.例如,在已经声明了 m(Object) 的类中声明 m(Object...) 会导致不再为某些调用表达式(例如 m(null))选择 m(Object),如 m(Object[]) 更具体.

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.

第二阶段在允许装箱和拆箱的同时执行重载决议,但仍排除使用变量arity方法调用.如果在此阶段找不到适用的方法,则处理继续到第三阶段.

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.

第三阶段允许重载与可变数量方法、装箱和拆箱相结合.

这篇关于Java:允许具有一个可变参数的函数和具有相同名称和一个相同类型参数的函数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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