Java@深入理解Java虚拟机:类加载机制( 三 )
- 接口方法解析
- 与类的方法解析相反 , 如果在接口方法表中发现class_index中的索引C是个类而不是接口 , 那么就直接抛出java.lang.IncomepatibleClassChangeError异常 。
- 否则 , 在接口C中查找是否有简单名称和描述符都与目标相匹配的方法 , 如果有则返回这个方法的直接引用 , 查找结束
- 否则 , 在接口C的父接口中递归查找 , 直到java.lang.Object类(接口方法的查找范围也会包括Object类中的方法)为止 , 看是否有简单名称和描述符都与目标相匹配的方法 , 如果有则返回这个方法的直接引用 , 查找结束 。
- 对于规则3 , 由于Java的接口允许多重继承 , 如果C的不同父接口中存有多个简单名称和描述符都与目标相匹配的方法 , 那将会从这多个方法中返回其中一个兵结束查找 。
- 否则 , 宣告方法查找失败 , 抛出java.lang.NoSuchMethodError异常 。
- 根据程序员通过程序编码指定的主观计划去初始化类变量和其他资源 。 (初始化阶段就是执行类构造器<clinit>()方法的过程) 。
- <clinit>()方法时有编译器自动收集类中的所有类变量的赋值动作和静态语句块(static{块)中的语句合并产生的 , 编译器收集的顺序是由语句在源文件中出现的顺序决定的 , 静态语句块中只能访问到定义在静态语句块之前的变量 , 定义在它之后的变量 , 在前面的静态语句块可以赋值 , 但是不能访问 。
- <clinit>()方法与类的构造函数(即在虚拟机视角中的实例构造器<init>()方法)不同 , 它不需要显式地调用父类构造器 , Java虚拟机会保证在子类的<clinit>()方法执行前 , 父类的<clinit>()方法已经执行完毕 。 因此在Java虚拟机中第一个被执行的<clinit>()方法的类型肯定是java.lang.Object 。
- 由于父类的<clinit>()先执行 , 也就意味着父类中定义的静态语句块要优先于子类的变量赋值操作 。
- <clinit>()方法对于类或接口来说并不是必须的 , 如果一个类中没有静态语句块 , 也没有对变量的赋值操作 , 那么编译器可以不为这个类生成<clinit>()方法 。
- 接口中不能使用静态语句块 , 但仍然有变量初始化的赋值操作 , 因此接口与类一样都会生成<clinit>()方法 。 但接口与类不同的是 , 执行接口的<clinit>()方法不需要先执行父接口的<clinit>()方法 , 因为只有父接口中定义的变量被使用时 , 父接口才会被初始化 。 此外 , 接口的实现类在初始化时也一样不会执行接口的<clinit>()方法 。
推荐阅读
- 木星:地球没事吧?太阳系最强烈暴风雨出现,却被要求深入探测
- Java@23种java设计模式之:建造者模式、工厂方法模式、抽象工厂模式!
- Java@深入理解Java虚拟机:高效并发之Java内存模型
- IT之家▲《后浪》策划团队回应刷屏:并不会反对一些不同的理解
- 【UFO】叹为观止,美方正式公布3段UFO视频,目击者:已经无法用常理解释
- UFO@美方正式公布3段UFO视频,目击者:已经无法用常理解释
- 「航天」人类寿命可达1000年,剩下的900年被谁拿走了?专家给出合理解释
- 「海报新闻客户端」优质鲁货深入对接电商平台“牵手”阿里、京东等扩大线上销售
- 『科学家』蚂蚁并非是二维生物,科学家发现多维度空间,人类一直理解错了
- 手机大魔王@深入分析华为Nova7,这款手机到底值不值?