首先先看没有继承关系的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这个程序 继承关系的初始化
java如何让自定义内容在项目启动后执行
转载本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
上一篇:成绩统计系统java
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
odoo的启动过程以及自定义脚手架
odoo的启动过程以及自定义脚手架
模版 自定义 main函数 -
详谈SpringBoot启动项目后执行自定义方法的方式
SpringBoot启动项目后执行自定义方法6种方式
启动 System sed ide -
java自定义注释是在代码前执行还是代码后执行 java自定义注解作用
1.概述 我们知道java面向对象的三大特征:封装 继承 多态。封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据。继承是为了重用父类代码,同时为实现多态性作准备。他们都有一个重要作用那就是----代码重用。那么多态是什么呢?我们知道java设计上只允许单个继承,这样做虽然保证了继承关系的简单明了,但是势必在功能上有很大的限制,所以,Java引入了多态性的概
java interface作用是什么 java 代码重用需要注意的事项 java 父类获取子类名称 java 自定义注解 java多态的理解