持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第9天,点击查看活动详情
动态语言和静态语言
- 动态类型语言和静态类型语言两者的区别就在于对类型的检查是在编译期还是在运行期,满足前者就是静态类型语言,反之是动态类型语言。
- 说的再直白一点就是,静态类型语言是判断变量自身的类型信息;动态类型语言是判断变量值的类型信息,变量没有类型信息,变量值才有类型信息,这是动态语言的一个重要特征。
Java:String info = “juejin”; (Java是静态类型语言的,会先编译就进行类型检查)
JS:var name = “juejin”; var name = 10; (运行时才进行检查)
Java语言中方法重写的本质
-
找到操作数栈顶的第一个元素所执行的对象的实际类型,记作C。
-
如果在类型C中找到与常量中的描述符合简单名称都相符的方法,则进行访问权限校验。
- 如果通过则返回这个方法的直接引用,查找过程结束
- 如果不通过,则返回java.lang.IllegalAccessError 异常
-
否则,按照继承关系从下往上依次对C的各个父类进行第2步的搜索和验证过程。
-
如果始终没有找到合适的方法,则抛出java.lang.AbstractMethodError异常。
上面这个过程称为动态分派
IllegalAccessError介绍
- 程序试图访问或修改一个属性或调用一个方法,这个属性或方法,你没有权限访问。一般的,这个会引起编译器异常。这个错误如果发生在运行时,就说明一个类发生了不兼容的改变。
- 比如,你把应该有的jar包放从工程中拿走了,或者Maven中存在jar包冲突
虚方法表
- 在面向对象的编程中,会很频繁的使用到动态分派,如果在每次动态分派的过程中都要重新在类的方法元数据中搜索合适的目标的话就可能影响到执行效率。因此,为了提高性能,JVM采用在类的方法区建立一个虚方法表(virtual method table)来实现,非虚方法不会出现在表中。使用索引表来代替查找。【上面动态分派的过程,我们可以看到如果子类找不到,还要从下往上找其父类,非常耗时】
- 每个类中都有一个虚方法表,表中存放着各个方法的实际入口。
- 虚方法表是什么时候被创建的呢?虚方法表会在类加载的链接阶段被创建并开始初始化,类的变量初始值准备完成之后,JVM会把该类的虚方法表也初始化完毕。
1、比如说son在调用toString的时候,Son没有重写过,Son的父类Father也没有重写过,那就直接调用Object类的toString。那么就直接在虚方法表里指明toString直接指向Object类。
2、下次Son对象再调用toString就直接去找Object,不用先找Son–>再找Father–>最后才到Object的这样的一个过程。