Java方法重载的本质

简介: Java方法重载的本质

背景


考大家一道题目,下面的类执行结果是什么???

public class DispatcherClient {
    public static void main(String[] args) {
        Animal a = new Animal();
        Animal a1 = new Dog();
        Animal a2 = new Cat();
        Execute exe = new Execute();
        exe.execute(a);
        exe.execute(a1);
        exe.execute(a2);
    }
}
 class Animal {
}
 class Dog extends Animal {
}
 class Cat extends Animal {
}
 class Execute {
    public void execute(Animal a) {
        System.out.println("Animal");
    }
    public void execute(Dog d) {
        System.out.println("dog");
    }
    public void execute(Cat c) {
        System.out.println("cat");
    }
}

不知道大家心里的答案是什么?反正我的答案是错的。

正确的答案是:

1671174105589.jpg

为什么是Animal Animal Animal? 而不是Animal dog cat


类重载本质——静态分派


execute方法是一个重载方法,本质上就是虚拟机JVM如何确定调用哪个方法执行。在java编译后的class文件中存储的只是方法的符号引用,而不是方法在实际运行过程中内存布局的入口地址(直接引用)。而这个方法从符号引用变成直接引用有两种方式,解析和分派。

解析是发生在类加载的解析阶段就会将一部分方法的符号引用转换为直接引用,比如类的静态方法、私有方法、构造方法、父类方法以及final的方法。我们这里不展开阐述,和本例无关。

而我们方法重载的情况下,java采用的是静态分派的方式确定调用方法。

变量类型

在了解静态分派前我们需要了解下变量的类型。

Animal a1 = new Dog();
  • 静态类型, 也叫做"外观类型", 比如代码中的"Animal", 它的类型是在编译期就知道。
  • 实际类型,也叫"运行时类型", 比如代码中的"Dog", 它是在类运行时才会确定,编译期是不知道的。
Execute exe = new Execute();
exe.execute(a);
exe.execute(a1);
exe.execute(a2);

这里多次调用了execute方法,在方法接收者已经确定是对象exe的前提下,使用哪个重载的方法,就完全取决于传入参数的数量和数据类型。虚拟机在重载时是通过参数的静态类型而不是实际类型作为判断依据的。因为静态类型是编译期可知的,所以,在编译阶段,编译器会根据静态类型决定使用哪个重载版本,如下图例子中的字节码,技术在编译的字节码中确定了它调用的重载方法。

1671174121504.jpg


总结


总结下,所有依赖静态类型来定位方法执行版本的分派叫做静态分派。静态分派的典型应用就是方法重载,它是在编译阶段确定的,它会选择一个最合适的版本方法进行调用。

目录
相关文章
|
5月前
|
Java 编译器 开发者
java方法重载详细说明
Java方法重载允许在同一类中定义多个同名但参数列表不同的方法,通过参数数量、类型或顺序的不同来区分。这提高了代码的可读性和灵活性。例如,在一个类中可以定义多个`add`方法,分别处理不同数量和类型的参数。重载的关键不在于返回类型或访问修饰符,而在于参数列表的差异。合理使用方法重载可以简化程序设计,使代码更加高效。
136 5
|
4月前
|
Java C++
java方法重载
java方法重载
34 0
|
9月前
|
安全 Java 编译器
深入理解Java语言中的方法重载(Overloading)
深入理解Java语言中的方法重载(Overloading)
189 1
|
8月前
|
存储 Java
Java基础手册(标识符 关键字 字面值 变量 数据类型 字符编码 运算符 控制语句 方法及方法重载和递归 面向对象与面向过程)
Java基础手册(标识符 关键字 字面值 变量 数据类型 字符编码 运算符 控制语句 方法及方法重载和递归 面向对象与面向过程)
55 0
|
9月前
|
Java 编译器
滚雪球学Java(36):玩转Java方法重载和可变参数,让你的代码更灵活
【5月更文挑战第11天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
53 0
|
9月前
|
Java 编译器
Java构造方法重载的深入探索
Java构造方法重载的深入探索
99 0
|
9月前
|
Java
java面试基础 -- 方法重载 & 方法重写
java面试基础 -- 方法重载 & 方法重写
48 0
|
自然语言处理 Java 编译器
Java方法的使用和方法重载
Java方法的使用和方法重载
104 0
|
9月前
|
自然语言处理 Java 编译器
【Java探索之旅】方法重载 递归
【Java探索之旅】方法重载 递归
50 0
|
9月前
|
Java 编译器
每日一道Java面试题:方法重载与方法重写,这把指定让你明明白白!
每日一道Java面试题:方法重载与方法重写,这把指定让你明明白白!
48 0