【9071期】为什么不同方法返回类型不算方法重载?

方法重载是指在同一个类中,定义了多个同名方法,但每个方法的参数类型或者是参数个数不同就是方法重载。

方法签名是由:方法名称 + 参数类型 + 参数个数组成的一个唯一值,这个唯一值就是方法签名,而 JVM(Java 虚拟机)就是通过这个方法签名来决定调用哪个方法的

从方法签名的组成规则我们可以看出,方法的返回类型不是方法签名的组成部分,所以当同一个类中出现了多个方法名和参数相同,但返回值类型不同的方法时,JVM 就没办法通过方法签名来判断到底要调用哪个方法了。

方法重载的经典使用场景是 String 类型的 valueOf 方法,valueOf 方法重载有 9 种实现。它可以将数组、对象和基础数据类型转换成字符串类型。

方法重载匹配原则

方法重载的调用顺序是有前后之分的,比如以下代码:

public class OverloadExample {
    public static void main(String[] args) {
        OverloadExample example = new OverloadExample();
        example.method(12);
    }

    public void method(int num) {
        System.out.println("调用 int 方法");
    }

    public void method(long num) {
        System.out.println("调用 long 方法");
    }

    public void method(Integer num) {
        System.out.println("调用 Integer 方法");
    }

    public void method(Object num) { 
        System.out.println("调用 Object 方法");
    }

    public void method(int... num) { // 可选参数
        System.out.println("调用 int... 方法");
    }
}

当出现方法重载时,程序要调用哪个方法呢?执行以上程序的执行结果如下:

【9071期】为什么不同方法返回类型不算方法重载?

匹配原则1:精准类型匹配

方法重载会优先调用和方法参数类型一模一样的方法,这是第一优先匹配原则:精准类型匹配。

匹配原则2:基本类型自动转换成更大的基本类型

接下来我们把精准匹配方法删掉,观察一下第二匹配顺序是什么?实现代码如下:

public class OverloadExample {
    public static void main(String[] args) {
        OverloadExample example = new OverloadExample();
        example.method(12);
    }

    public void method(long num) {
        System.out.println("调用 long 方法");
    }

    public void method(Integer num) {
        System.out.println("调用 Integer 方法");
    }

    public void method(Object num) { 
        System.out.println("调用 Object 方法");
    }

    public void method(int... num) { // 可选参数
        System.out.println("调用 int... 方法");
    }
}

以上程序的执行结果如下图所示:

【9071期】为什么不同方法返回类型不算方法重载?

因此我们可以得出结论:如果是基本数据类型,那么方法重载调用的第二匹配原则是自动转换成更大的基本数据类型

匹配原则3:自动装/拆箱匹配

接下来将第二匹配原则中的 long 方法也删除掉,实现代码如下:

public class OverloadExample {
    public static void main(String[] args) {
        OverloadExample example = new OverloadExample();
        example.method(12);
    }

    public void method(Integer num) {
        System.out.println("调用 Integer 方法");
    }

    public void method(Object num) {
        System.out.println("调用 Object 方法");
    }

    public void method(int... num) { // 可选参数
        System.out.println("调用 int... 方法");
    }
}

【9071期】为什么不同方法返回类型不算方法重载?

从上述执行结果可以看出,方法重载的第三匹配原则是,匹配自动装箱或拆箱的数据类型

匹配原则4:按照继承路线依次向上匹配

此时将第三匹配原则中的 Integer 方法删除,剩下的代码如下:

public class OverloadExample {
    public static void main(String[] args) {
        OverloadExample example = new OverloadExample();
        example.method(12);
    }

    public void method(Object num) {
        System.out.println("调用 Object 方法");
    }

    public void method(int... num) { // 可选参数
        System.out.println("调用 int... 方法");
    }
}

以上程序的执行结果如下图所示:

【9071期】为什么不同方法返回类型不算方法重载?

从上述执行结果可以看出,方法重载的第四匹配原则是,依次向上匹配父类的方法调用

匹配原则5:可变参数匹配

最后将代码中的方法删除的只剩一个可选参数,实现代码如下:

public class OverloadExample {
    public static void main(String[] args) {
        OverloadExample example = new OverloadExample();
        example.method(12);
    }

    public void method(int... num) { // 可选参数
        System.out.println("调用 int... 方法");
    }
}

从上述执行结果可以看出,方法重载的第五匹配原则是,匹配可选参数。

总结

在同一个类中定义了多个同名方法,但每个方法的参数类型或者是参数个数不同就是方法重载。方法重载的典型使用场景是 String 中的 valueOf 方法,它有 9 种实现。方法返回类型不能作为方法重载的依据,因为它不是方法签名的组成部分。方法重载有 5 个匹配原则:精准匹配、基本类型自动转换成更大的基本类型匹配、自动装/拆箱匹配、按照继承路线依次向上匹配、可变参数匹配。

 

上一篇:C# 10 新功能总结


下一篇:endnote教程:参考文献出现{zhang,2020,#365} 修改方法