JAVA类的加载和对象初始化过程
2018-02-19 00:00
465 查看
迟迟未总结的关于java类加载的相关知识,主要参考了大神们的博客,加上自己的实践和总结。理解错误的地方欢迎指正。
参考的博客:
http://blog.csdn.net/lincolnmi/article/details/50539463 http://blog.csdn.net/zjl477595675/article/details/48101611 http://blog.csdn.net/u011080472/article/details/51330114 http://blog.csdn.net/woshichuanqihan/article/details/49229641
-----------------------------------------------------------------------------------------------------------
类的初始化和对象的初始化是两个不同的概念。
1)类的初始化是类加载过程中的一个阶段,对静态变量和静态代码块进行初始化,不会调用类的构造方法。
2)对象的初始化是在类加载完成后为对象分配内存,实例变量的初始化(为变量赋值默认值,比如int a 默认为0),实例变量的赋值及调用类构造方法完成对象的初始化过程。
类的初始化发生在类未加载的时候,且只加载一次。每个对象都有自己对象的初始化过程。
init main
Example1 静态代码块
SonOfExample1 静态代码块
Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
Java虚拟机在主动使用某个类的时候加载类,当发现其父类未加载会先加载父类(按出现顺序执行父类的静态代码块和静态变量赋值),被动使用的时候不加载类。
(a)主动使用
1)创建某个类的新实例(new,反射,克隆或反序列化);
2)调用类的静态方法;
3)使用某个类的静态字段,用final修饰的静态常量字段除外(static final int likeyou= 21);
4)调用Java API中的反射方法
(b)被动应用
1) 调用类的静态字段(静态变量【非静态常量】和静态方法),只有直接定义这个静态字段的类才会被加载。例如:子类引用父类中静态字段,只会触发父类的加载,不会触发子类的加载。
2)调用类的静态常量是不触发类的加载过程。例如:子类引用父类中静态常量,父类和子类都不会加载。
只执行 System.out.println(SonOfExample1.jtbl);//静态变量
init main
Example1 静态代码块
20
------------------------------------------------------------------------------------------------
只执行 System.out.println(SonOfExample1.jtcl);//静态常量
init main
30
类的加载过程:加载,连接(包括:验证,准备,解析),类的初始化,使用,卸载。
现在来分析下第一个例子中的打印的顺序
init main
Example1 静态代码块
SonOfExample1 静态代码块
Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
当执行main方法的时候,main方法是静态方法,首先要对这个类进行加载。
打印 init main
当执行 SonOfExample1 s1= new SonOfExample1();
首先加载SonOfExample1 类,发现其有父类,加载父类,直至Object类,然后执行完父类的加载过程,再执行子类的加载过程,
打印 Example1 静态代码块
SonOfExample1 静态代码块
加载完类之后,执行对象的初始化过程,执行new SonOfExample1(),执行子类构造方法的时候,父类的构造会被调用,因此出发父类对象的初始化过程,
打印 Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
当执行 SonOfExample1 s2= new SonOfExample1();
子类和父类已经被初始化了,因此不会再加载类了,就没有静态部分相关内容的执行,执行new SonOfExample1(),执行子类构造方法的时候,父类的构造会被调用,因此出发父类对象的初始化过程
打印 Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
参考的博客:
http://blog.csdn.net/lincolnmi/article/details/50539463 http://blog.csdn.net/zjl477595675/article/details/48101611 http://blog.csdn.net/u011080472/article/details/51330114 http://blog.csdn.net/woshichuanqihan/article/details/49229641
-----------------------------------------------------------------------------------------------------------
类的初始化和对象的初始化是两个不同的概念。
1)类的初始化是类加载过程中的一个阶段,对静态变量和静态代码块进行初始化,不会调用类的构造方法。
2)对象的初始化是在类加载完成后为对象分配内存,实例变量的初始化(为变量赋值默认值,比如int a 默认为0),实例变量的赋值及调用类构造方法完成对象的初始化过程。
类的初始化发生在类未加载的时候,且只加载一次。每个对象都有自己对象的初始化过程。
public class Example1 { protected int a =10; public static int bb=20; static { System.out.println("Example1 静态代码块"); } { System.out.println("Example1 代码块"); } public Example1(){ System.out.println("Example1 构造函数"); } } public class SonOfExample1 extends Example1 { static { System.out.println("SonOfExample1 静态代码块"); } { System.out.println("SonOfExample1 代码块"); } public SonOfExample1() { super(); System.out.println("SonOfExample1 构造函数"); } } public class ExampleMain { static { System.out.println("init main"); } public static void main(String[] args) { SonOfExample1 s1= new SonOfExample1(); SonOfExample1 s2= new SonOfExample1(); } }
init main
Example1 静态代码块
SonOfExample1 静态代码块
Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
类的加载
类编译后都对应一个class文件,一般情况下只加载一次。类的加载过程包括几个阶段:加载,连接(包括:验证,准备,解析),类的初始化,使用,卸载。Java虚拟机在主动使用某个类的时候加载类,当发现其父类未加载会先加载父类(按出现顺序执行父类的静态代码块和静态变量赋值),被动使用的时候不加载类。
(a)主动使用
1)创建某个类的新实例(new,反射,克隆或反序列化);
2)调用类的静态方法;
3)使用某个类的静态字段,用final修饰的静态常量字段除外(static final int likeyou= 21);
4)调用Java API中的反射方法
(b)被动应用
1) 调用类的静态字段(静态变量【非静态常量】和静态方法),只有直接定义这个静态字段的类才会被加载。例如:子类引用父类中静态字段,只会触发父类的加载,不会触发子类的加载。
2)调用类的静态常量是不触发类的加载过程。例如:子类引用父类中静态常量,父类和子类都不会加载。
public class Example1 { protected int a =10; public static int jtbl=20; public final static int jtcl=30; static { System.out.println("Example1 静态代码块"); } { System.out.println("Example1 代码块"); } public Example1(){ System.out.println("Example1 构造函数"); } } public class SonOfExample1 extends Example1 { static { System.out.println("SonOfExample1 静态代码块"); } { System.out.println("SonOfExample1 代码块"); } public SonOfExample1() { System.out.println("SonOfExample1 构造函数"); } } public class ExampleMain { static { System.out.println("init main"); } public static void main(String[] args) { System.out.println(SonOfExample1.jtbl);//静态变量 //System.out.println(SonOfExample1.jtcl);//静态常量 } }
只执行 System.out.println(SonOfExample1.jtbl);//静态变量
init main
Example1 静态代码块
20
------------------------------------------------------------------------------------------------
只执行 System.out.println(SonOfExample1.jtcl);//静态常量
init main
30
类的加载过程:加载,连接(包括:验证,准备,解析),类的初始化,使用,卸载。
【1】加载阶段
根据类的路径定位及加载class文件,在java堆中生成一个代表这个类的java.lang.Class对象。【2】连接阶段
1)验证阶段
确保class文件的信息符合当前虚拟机的要求2)准备阶段
正式为静态变量分配内存及设置静态变量的默认值(实例变量是在对象实例化时和对象一起在堆中分配内存)3)解析阶段
将常量池内的符号引用替换为直接应用【3】类的初始化
执行类的静态变量赋值和静态代码块,如果父类没有加载,会执行父类的静态变量赋值和静态代码块。对象的初始化
对象初始化过程包括类加载过程(类加载过了就不含该过程),对象内存分配,设置默认值,赋值操作,执行构造方法。现在来分析下第一个例子中的打印的顺序
init main
Example1 静态代码块
SonOfExample1 静态代码块
Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
当执行main方法的时候,main方法是静态方法,首先要对这个类进行加载。
打印 init main
当执行 SonOfExample1 s1= new SonOfExample1();
首先加载SonOfExample1 类,发现其有父类,加载父类,直至Object类,然后执行完父类的加载过程,再执行子类的加载过程,
打印 Example1 静态代码块
SonOfExample1 静态代码块
加载完类之后,执行对象的初始化过程,执行new SonOfExample1(),执行子类构造方法的时候,父类的构造会被调用,因此出发父类对象的初始化过程,
打印 Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
当执行 SonOfExample1 s2= new SonOfExample1();
子类和父类已经被初始化了,因此不会再加载类了,就没有静态部分相关内容的执行,执行new SonOfExample1(),执行子类构造方法的时候,父类的构造会被调用,因此出发父类对象的初始化过程
打印 Example1 代码块
Example1 构造函数
SonOfExample1 代码块
SonOfExample1 构造函数
相关文章推荐
- java类和对象的加载过程
- java 程序加载过程---3--类中申明同时申明类的静态对象 创建类的实例 访问类的静态变量 调用类的静态方法 使用反射方法 初始化类的子类对象 直接使用java.exe 调用某个类
- java程序在执行过程中,类,对象以及它们成员加载、初始化的顺序如下:
- Java类加载及变量初始化过程
- [Java]java类加载及new对象的过程
- 类加载和对象的初始化过程
- java类加载、对象创建过程
- java类加载及new对象的过程
- Webkit初始化以及加载URL过程中各种对象的建立时序以及DOM树的建立详情分析
- Java类加载初始化的过程
- java类从加载、连接到初始化过程详解
- java中一个对象的初始化过程
- Webkit初始化以及载入URL过程中各种对象的建立时序以及DOM树的建立详情分析
- 对象的初始化过程
- 面向对象--对象的初始化过程
- Java 创建对象时的初始化过程
- linux文件系统初始化过程(3)---加载initrd(上)
- 菜鸟柳---对象初始化过程顺序分析(子父类)
- java类加载过程
- Java中子类对象初始化的过程