java中有关初始化的一些知识的笔记

本文详细解析了Java类的初始化过程,包括构造器的作用、静态初始化的特点以及类继承关系下的类加载机制。重点阐述了类初始化的六个步骤:构造器与静态方法的加载、对象实例化、字段初始化、构造器调用,同时讨论了继承关系下类加载的顺序和静态成员的初始化。
首先先看没有继承关系的Dog对象的创建过程

1、构造器也是静态方法,当首次创建dog对象的时候,或者dog类的静态方法/静态域首次被访问的时候,解释器要定位class文件

2、载入class后,有关静态初始化的所有动作都会执行,
(静态初始化只在Class对象首次加载的时候执行一次)

3、当用new来创建对象的时候,会在堆上位对象分配足够的空间

4、这块存储空间会被清零,就相当于初始化了(自动初始化可能就是在这一步)

5、执行所有出现在字段定义处的初始化
(也就是所有实时变量的初始化,你的制定初始化在这一步完成)

6、执行构造器
(执行构造器的作用也是初始化,你可以不指定初始化,在构造器中对一些变量初始化)


对于static的理解,我发现static很重要,与其说是为了访问构造器才加载倒不如说是为了访问静态的东西才加载static的
static在P29页中 static的意义是描述了一个类的属性,而非是单个的对象的属性

但是感觉从编译的角度来讲,好像程序首先会无条件的加载静态的东西
main入口点就是一个静态方法,我觉得main方法,是一个过程性的脚本,它直接指示了
我们所有的类做些什么怎么做,就像一个脚本,演员已经有了(我们定义的那些类),我们要指示什么时候他们做什么,我觉得main方法就是干这个用的
这个就是面向对象中的唯一一块面向过程的部分,以为脚本嘛,就是一个面向过的东西

所以当main方法被访问后,整个程序就运行起来了

静态的东西首先会放到内存的低位(?)
确定的东西摆一堆,然后不确定的东西再摆一堆


对于P146 beetle.java这个程序

对于有继承关系的情况下,情况会有点不一样


当开始加载包含有main方法的类的class文件的时候,如果这个类有基类(编译器从extends关键字得知),那么编译器自动会加载这个类的基类的class文件(不管你有没有打算产生这个基类的对象),如果基类还有基类,那么就继续加载,依此类推。
为啥这样呢,因为导出类的static初始化可能会依赖于基类成员是否能正确的初始化。

这一点不像上面那种情况,上一个程序那个,是由于初始化静态域的过程中,静态域中有初始化其他类的语句,所以才加载其他类的class对象


在什么情况下会加载class文件
(1)访问某一个类的静态对象(静态域/静态方法)的时候,如果是第一次访问就会加载这个类的class文件,由于构造器也属于静态方法,所以初始化的时候也会加载类的class文件
应该只是加载一次吧,一旦加载了class文件,然后初始化静态域吧,这个也是进行一次

(2)还有就是要加载的类有基类的情况,那么会自动加载基类的class
这种情况下仅仅加载并且初始化静态域就为止


如果是由于调用构造器那么就会执行从加载到初始化变量到调用构造器整个过程
这个过程可以分成两半

实际上初始化的这个过程可以分成两个部分

单独的类的初始化可以分成两个部分

一个是加载class文件到初始化所有的静态域这个一部分
然后就是自动初始化、所有字段定义处的初始化,调用构造器这是第二部分

其实这两个部分并不是必然联系在一起的,只有当调用构造器的时候,这两个部分才连接在一起执行
有的时候比方说有基类的类的初始化的情况下,也可能仅仅进行第一部分的过程

首先是从导出类到基类的所有class文件加载完毕后,再从基类的static开始依次初始化


然后再回到这个程序中
必要的类加载完毕,基类和当前类的静态部分也初始化好了
回到main方法中
输出 Beetle constructor
执行 Beetle b=new Beetle();
执行这一句后会发生什么呢?按理来说说是加载类,静态部分,但是之前已经做过了
所以就进行初始化的第二部分
在分配空间置零之后,定义字段初始化之前
会调用基类的构造函数,然后在执行基类构造函数之前还会进行
空间的分配和实例变量的初始化(虽然书上没有这么说,但是书上有一句“基类构造器和导出类的构造器一样,以相同的顺序来经历相同的过程” 另外如果没有进行实例的初始化,那么输出i的值不可能是9的)然后执行基类的构造函数,基类构造函数执行完之后,返回子类
子类的实例变量进行初始化,然后执行子类的构造函数


所以最后的结论是
每一次调用构造器之前,都会先调用基类的构造器,
如果有基类,在子类的分配空间置零之后,实例变量初始化之前会调用基类的构造器
而基类还有基类的话,以此类推,直到最后一个基类
在执行最后一个基类构造期之前会进行空间的分配,实例变量初始化,然后执行构造器
然后返回下一个子类


初始化分为两个部分

初始化第一部分
加载class、静态部分初始化

初始化第二部分
分配空间置零、
定义字段初始化、(实例变量初始化)
构造器


抓住两点
首先先初始化父类再初始化子类
在调用构造器之前首先会初始化实例变量


几个比较重要的程序

P95 StaticInitialization.java 单个的含有静态部分的对象的初始化

对于P146 beetle.java这个程序 继承关系的初始化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值