一文理解java对象初始化顺序
例子
Talk is cheap, Show you the code!
public class ParentClass {
static int parentStaticField = 1;
final static int parentFinalStaticField = 2;
int parentSubField = 3;
static {
System.out.println("parent static!");
System.out.println("SubStatic field:" + SubClass.subStaticField);
System.out.println("SubFinalStatic field:" + SubClass.subFinalStaticField);
System.out.println("ParentStatic field:" + parentStaticField);
System.out.println("ParentFinalStatic field:" + parentFinalStaticField);
}
{
System.out.println("parent not static!");
System.out.println("SubStatic field:" + SubClass.subStaticField);
System.out.println("SubFinalStatic field:" + SubClass.subFinalStaticField);
System.out.println("ParentStatic field:" + parentStaticField);
System.out.println("ParentFinalStatic field:" + parentFinalStaticField);
System.out.println("Parent field:" + parentSubField);
}
public ParentClass() {
System.out.println("parent construct!");
}
}
public class SubClass extends ParentClass {
static int subStaticField = 1;
final static int subFinalStaticField = 2;
int subField = 3;
static {
System.out.println("Sub static!");
System.out.println("SubStatic field:" + SubClass.subStaticField);
System.out.println("SubFinalStatic field:" + SubClass.subFinalStaticField);
}
{
System.out.println("Sub no static!");
System.out.println("SubStatic field:" + SubClass.subStaticField);
System.out.println("SubFinalStatic field:" + SubClass.subFinalStaticField);
}
public SubClass() {
System.out.println("Sub Construct!");
}
public static void main(String[] args) {
new SubClass();
}
}
输出:
parent static! --- 父类静态代码块
SubStatic field:0
SubFinalStatic field:2
ParentStatic field:1 --- 父类静态代码块调用之前静态属性已经初始化
ParentFinalStatic field:2
Sub static! --- 子类静态代码块
SubStatic field:1
SubFinalStatic field:2
parent not static! --- 父类非静态代码块
SubStatic field:1
SubFinalStatic field:2
ParentStatic field:1
ParentFinalStatic field:2
Parent field:3
parent construct! --- 父类构造函数
Sub no static! --- 子类非静态代码块
SubStatic field:1
SubFinalStatic field:2
Sub Construct! --- 子类构造函数
从上面的例子总结类初始化的时候代码的执行顺序如下:
父类和子类的
final static属性初始化 ---》 父类的static属性初始化---》父类的static代码块---》子类的
static属性初始化---》子类的static代码块 ---》父类的非静态属性 ---》父类的非静态代码块---》父类的构造函数 ---》 子类的非静态属性---》 子类的非静态代码块---》子类的构造含不管父类还是子类,静态还是非静态,属性的初始化时间在代码块执行之前
static final修饰的属性,不管是父类还是子类,在类加载的准备阶段就已经初始化了,他要优先于任何代码块和属性的初始化
细说
类的加载阶段
1、加载
由类加载器负责根据一个类的全限定名来读取此类的二进制字节流到JVM内部,并存储在运行时内存区的方法区,然后将其转换为一个与目标类型对应的java.lang.Class对象实例
2、验证
格式验证:验证是否符合class文件规范
语义验证:检查一个被标记为final的类型是否包含子类;检查一个类中的final方法是否被子类进行重写;
确保父类和子类之间没有不兼容的一些方法声明(比如方法签名相同,但方法的返回值不同)
操作验证:在操作数栈中的数据必须进行正确的操作,对常量池中的各种符号引用执行验证(通常在解析阶段执行,检查是否可以通过符号引用中描述的全限定名定位到指定类型上,以及类成员信息的访问修饰符是否允许访问等)
3、准备
为类中的所有静态变量分配内存空间,并为其设置一个初始值(由于还没有产生对象,实例变量不在此操作范围内)
被final修饰的static变量(常量),会直接赋值;
4、解析
将常量池中的符号引用转为直接引用(得到类或者字段、方法在内存中的指针或者偏移量,以便直接调用该方法),这个可以在初始化之后再执行。
解析需要静态绑定的内容。 // 所有不会被重写的方法和域都会被静态绑定
以上2、3、4三个阶段又合称为链接阶段,链接阶段要做的是将加载到JVM中的二进制字节流的类数据信息合并到JVM的运行时状态中。
5、初始化(先父后子)
为静态变量赋值
执行static代码块
注意:static代码块只有jvm能够调用
如果是多线程需要同时初始化一个类,仅仅只能允许其中一个线程对其执行初始化操作,其余线程必须等待,只有在活动线程执行完对类的初始化操作之后,才会通知正在等待的其他线程。
因为子类存在对父类的依赖,所以类的加载顺序是先加载父类后加载子类,初始化也一样。不过,父类初始化时,子类静态变量的值也有有的,是默认值。
最终,方法区会存储当前类类信息,包括类的静态变量、类初始化代码(定义静态变量时的赋值语句 和 静态初始化代码块)、实例变量定义、实例初始化代码(定义实例变量时的赋值语句实例代码块和构造方法)和实例方法,还有父类的类信息引用。
对象创建阶段
1、在堆区分配对象需要的内存
分配的内存包括本类和父类的所有实例变量,但不包括任何静态变量
2、对所有实例变量赋默认值
将方法区内对实例变量的定义拷贝一份到堆区,然后赋默认值
3、执行实例初始化代码
初始化顺序是先初始化父类再初始化子类,初始化时先执行实例代码块然后是构造方法
4、如果有类似于Child c = new Child()形式的c引用的话,在栈区定义Child类型引用变量c,然后将堆区对象的地址赋值给它
需要注意的是,每个子类对象持有父类对象的引用,可在内部通过super关键字来调用父类对象,但在外部不可访问
补充:
通过实例引用调用实例方法的时候,先从方法区中对象的实际类型信息找,找不到的话再去父类类型信息中找。
如果继承的层次比较深,要调用的方法位于比较上层的父类,则调用的效率是比较低的,因为每次调用都要经过很多次查找。这时候大多系统会采用一种称为虚方法表的方法来优化调用的效率。
所谓虚方法表,就是在类加载的时候,为每个类创建一个表,这个表包括该类的对象所有动态绑定的方法及其地址,包括父类的方法,但一个方法只有一条记录,子类重写了父类方法后只会保留子类的。当通过对象动态绑定方法的时候,只需要查找这个表就可以了,而不需要挨个查找每个父类。
参考链接
一文理解java对象初始化顺序的更多相关文章
- Java变量、Java对象初始化顺序
局部变量与成员变量: 局部变量分为: 行参:在方法签名中定义的局部变量,随方法的结束而凋亡. 方法内的局部变量:必须在方法内对其显示初始化,从初始化后开始生效,随方法的结束而凋亡. 代码块内的局部变量 ...
- Java对象初始化顺序
最近我发现了一个有趣的问题,这个问题的答案乍一看下骗过了我的眼睛.看一下这三个类: package com.ds.test; public class Upper { String upperSt ...
- java对象初始化顺序的简单验证
以下这段小程序对调用对象构造函数时,父类构造函数.成员变量初始化函数,以及非静态初始化块调用顺序进行验证,不考虑静态成员及静态初始化块. public class Derive extends Bas ...
- 深入理解Java对象的创建过程:类的初始化与实例化
摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的.在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类 ...
- (转)深入理解Java对象的创建过程
参考来源:http://blog.csdn.net/justloveyou_/article/details/72466416 摘要: 在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一 ...
- Java提高篇——静态代码块、构造代码块、构造函数以及Java类初始化顺序
静态代码块:用staitc声明,jvm加载类时执行,仅执行一次构造代码块:类中直接用{}定义,每一次创建对象时执行.执行顺序优先级:静态块,main(),构造块,构造方法. 构造函数 public H ...
- java 继承 初始化顺序
面向对象三大特性: 封装,继承,多态 java 继承初始化顺序 先初始化父类对象, 在父类对象中先初始化父类属性,再初始化父类的构造方法,然后初始化子类对象,初始化子类对象的属性,初始化子类的构造方法 ...
- java继承 初始化顺序
java继承 初始化顺序 标签: 初始化顺序 2013-08-01 10:13 879人阅读 评论(0) 收藏 举报 分类: java(8) 版权声明:本文为博主原创文章,未经博主允许不得转载. ...
- 深入理解Java对象
深入理解Java对象(理清关系) 1.对象的创建过程: 所有创建过程如下所示: new 类名 根据new的参数在常量池中定位一个类的符号引用. 如果没有找到这个符号引用,说明类还没有被加载,则进行类的 ...
随机推荐
- SpringBoot集成Shiro 实现动态加载权限
一.前言 本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,不用重启项目,以及在页面分配给用户 角色 . 按钮 .ur ...
- Maven 梳理 - maven新建web项目提示"javax.servlet.http.HttpServlet" was not found on the Java Build Path
方法一: <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api&l ...
- Spring 梳理-MVC-配置DispatcherServet和ContextLoaderListener
在使用JavaConfig时,AbstractAnnotationConfigDispatcherServletInitializer会自动注册 DispatcherServlet 和 Context ...
- Case1-basic network framework/Related organization‘s name
常见的计算机网络物理拓扑结构: 1.星型网 2.树型网 3.分布式网络 4.总线型网 5.环型网 6.复合型网络 计算机网络相关的标准化组织: 国际标准化组织(ISO):International O ...
- mkdir,rmdir
mkdir (选项)(参数) 创建文件夹-m:创建文件夹的同时,赋予其权限-p:若创建目录的上层不存在时,一并创建出来-v:显示创建的过程创建多个目录的时候,用空格隔开 rmdir (选项)(参数) ...
- Fast Earth - 文本 绘制,如何实现三维空间中绘制屏幕大小的文字?
如题:先上一张图,在说是如何实现的 实现上图效果,有如下三种方式: 1. 屏幕坐标绘制点要素,即将经纬度坐标转换成屏幕坐标方式绘制,大多数GIS系统都是采用这种方式: 优点:实现方式简单,效果较好 缺 ...
- Scala 学习笔记之集合(1)
package com.citi.scala object CollectionDemo { def main(args: Array[String]): Unit = { /** * List */ ...
- MongoDB 学习笔记之 手动预先分片
手动预先分片: 目的:手动预先分片是为了防止未来chunk的移动,减少IO. sh.shardCollection("shop.users",{"userId" ...
- B-概率论-极大似然估计
[TOC] 更新.更全的<机器学习>的更新网站,更有python.go.数据结构与算法.爬虫.人工智能教学等着你:https://www.cnblogs.com/nickchen121/ ...
- Road Construction
King Mercer is the king of ACM kingdom. There are one capital and some cities in his kingdom. Amazin ...