面试官:来说说,啥叫个面向对象的三大特征:
我:封装、继承、多态
…
面试官:完了?
我:完了
…
害怕不,害怕就要提前多看看多学学喽
/**
* Copyright (c) 2013-Now http://AIminminAI.com All rights reserved.
*/
/**
* 方法静态分派演示
* @author HHB
* @version 2022年4月15日
*/
public class StaticDispatch {
/**
* 定义一个静态内部抽象类
*
* @author HHB
* @version 2022年4月15日
*/
static abstract class Apple {
}
static class BigApple extends Apple {
}
static class SmallApple extends Apple {
}
/**
* 三个重载的方法
* @param apple
* @author HHB
*/
public void eatApple(Apple apple) {
System.out.println("eat apple");
}
public void eatApple(BigApple apple) {
System.out.println("eat bigApple");
}
public void eatApple(SmallApple apple) {
System.out.println("eat smallApple");
}
public static void main(String[] args) {
Apple bigApple = new BigApple();
Apple samllApple = new SmallApple();
StaticDispatch staticDispatch = new StaticDispatch();
staticDispatch.eatApple(bigApple);
staticDispatch.eatApple(samllApple);
}
}
运行结果,咋是这呢?对我这种菜鸟来说,为啥嘞
挖一挖呗:
首先说,啥叫静态类型发生变化或者动态类型发生变化呢:
虚拟机(准确说是编译器)在重载时是通过传进来的参数的静态类型(静态类型是编译器可知的)而不是实际类型作为判定依据的
,也就是说Javac编译器会根据参数的静态类型决定使用哪个重载版本,这里静态类型的重载版本不就只有打印eat apple那一个嘛,所以选了这个eatApple(Apple apple)进行调用并把这个方法的符号引用写到main()方法中的两条invokevirtual指令的参数中
- 静态分派:上面这种依靠静态类型来定位方法执行版本的分派动作叫做静态分派。静态分派发生在编译阶段(啥东西,从哪里蹦出来一个分派,分派和解析是在不同层次上去筛选、确定目标方法的过程~解析看这一篇)
- 静态分派的典型应用就是方法重载
/**
* Copyright (c) 2013-Now http://AIminminAI.com All rights reserved.
*/
/**
*
* @author HHB
* @version 2022年4月15日
*/
public class DynamicDispatcher {
static abstract class Apple{
protected abstract void eatApple();
}
static class BigApple extends Apple{
@Override
protected void eatApple() {
System.out.println("eat bigApple");
}
}
static class SmallApple extends Apple{
@Override
protected void eatApple() {
System.out.println("eat samllApple");
}
}
public static void main(String[] args) {
Apple bigApple = new BigApple();
Apple smallApple = new SmallApple();
bigApple.eatApple();
smallApple.eatApple();
bigApple = new SmallApple();
bigApple.eatApple();
}
}
这个运行结果就很和善了嘛
那咱们和上面静态分派一样,可不得再看看到底调用的是哪个方法呢?上面咱们静态分派时传入的两个实际类型不一样,那这个呢?
- 动态分派:这里其实是两次方法调用中的invokevirtual指令**
把常量池中的类方法符号引用解析到了不同的直接引用(也就是句柄嘛,对象的直接引用哦)上,这也是Java中方法重写的本质
~直接引用看这里。咱们把这种在运行期根据实际类型确定方法执行版本的分派过程称为动态分配
**
巨人的肩膀:
深入理解Java虚拟机