java类成员变量与代码块初始化
首先根据下面的这个一段代码:引入关于java初始化顺序的问题
public class InitationTest extends Person {
public InitationTest() {
System.out.println("InitationTest constructor");
} static int j = 10;
static {
System.out.println("j="+j);
System.out.println("InitationTest static...");
} public static void main(String[] args) {
InitationTest obj = new InitationTest();
}
} class Person {
static {
// System.out.println("i="+i); Cannot reference a field before it is
// defined
i = 10;
System.out.println("Person static...");
}
static int i = 5; Person() {
System.out.println("Person constructor");
}
}
打印依次为:
Person static...
j=10
InitationTest static...
Person constructor
InitationTest constructor
想要理解类中初始化顺序,就必须先理解jvm加载原理
一:jvm加载顺序和原理
类的初始化顺序有点类似jvm中类加载器的模式:(双亲委派模型)的工作过程为:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的加载器都是如此,因此所有的类加载请求都会传给顶层的启动类加载器,只有当父加载器反馈自己无法完成该加载请求(该加载器的搜索范围中没有找到对应的类)时,子加载器才会尝试自己去加载。都是从父类中开始,当然类加载器并不是继承关系而是组合关系.
类从被加载到虚拟机内存中开始,到卸载出内存为止,它的生命周期包括了:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)、卸载(Unloading)七个阶段,其中验证、准备、解析三个部分统称链接

1.加载:
1.通过“类全名”来获取定义此类的二进制字节流
2.将字节流所代表的静态存储结构转换为方法区的运行时数据结构
3.在java堆中生成一个代表这个类的java.lang.Class对象,作为方法区这些数据的访问入口
2.验证:
1.文件格式验证
2.元数据验证
3.字节码验证
4.符号引用验证
3.准备:
准备阶段是正式为类变量分配内存并设置类变量初始值的阶段,这些内存都将在方法区中进行分配。这个阶段中有两个容易产生混淆的知识点,首先是这时候进行内存分配的仅包括类变量(static 修饰的变量),而不包括实例变量,实例变量将会在对象实例化时随着对象一起分配在java堆中。其次是这里所说的初始值“通常情况”下是数据类型的零值,假设一个类变量定义为:
public static int value = 12;
那么变量value在准备阶段过后的初始值为0而不是12,因为这时候尚未开始执行任何java方法,而把value赋值为12的putstatic指令是程序被编译后,存放于类构造器<clinit>()方法之中,所以把value赋值为12的动作将在初始化阶段才会被执行。
上面所说的“通常情况”下初始值是零值,那相对于一些特殊的情况,如果类字段的字段属性表中存在ConstantValue属性,那在准备阶段变量value就会被初始化为ConstantValue属性所指定的值,建设上面类变量value定义为:
public static final int value = 123;
编译时javac将会为value生成ConstantValue属性,在准备阶段虚拟机就会根据ConstantValue的设置将value设置为123
4.解析:
解析阶段是虚拟机常量池内的符号引用替换为直接引用的过程
5.初始化:
类的初始化阶段是类加载过程的最后一步,在准备阶段,类变量已赋过一次系统要求的初始值,而在初始化阶段,则是根据程序员通过程序制定的主观计划去初始化类变量和其他资源,或者可以从另外一个角度来表达:初始化阶段是执行类构造器<clinit>()方法的过程。在以下四种情况下初始化过程会被触发执行:
1.遇到new、getstatic、putstatic或invokestatic这4条字节码指令时,如果类没有进行过初始化,则需先触发其初始化。生成这4条指令的最常见的java代码场景是:使用new关键字实例化对象、读取或设置一个类的静态字段(被final修饰、已在编译器把结果放入常量池的静态字段除外)的时候,以及调用类的静态方法的时候。
2.使用java.lang.reflect包的方法对类进行反射调用的时候
3.当初始化一个类的时候,如果发现其父类还没有进行过初始化、则需要先出发其父类的初始化
4.jvm启动时,用户指定一个执行的主类(包含main方法的那个类),虚拟机会先初始化这个类
在上面准备阶段 public static int value = 12; 在准备阶段完成后 value的值为0,而在初始化阶调用了类构造器<clinit>()方法,这个阶段完成后value的值为12。
*类构造器<clinit>()方法是由编译器自动收集类中的所有类变量的赋值动作和静态语句块(static块)中的语句合并产生的,编译器收集的顺序是由语句在源文件中出现的顺序所决定的,静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句快可以赋值,但是不能访问。
二:加载顺序:
(1)静态内容:静态的成员变量、静态代码块、静态的成员方法按顺序加载。
(2)非静态内容:成员变量、代码块、成员方法按顺序加载。
总顺序:静态内容--》非静态内容--》类构造方法
编译器生成的class文件主要对定义在源文件中的类进行了如下的更改:
1) 先按照(静态or非静态)成员变量的定义顺序在类内部声明成员变量。
2) 再按照原java类中对(静态or非静态)成员变量的初始化顺序进行初始化。
左图是源文件,右图类似编译后的文件:

java类成员变量与代码块初始化的更多相关文章
- java中成员变量、代码块、构造函数运行顺序
1.java虚拟机执行程序,首先须要装载类,安装现装载父类,初始化父类的静态代码块和静态成员变量 再load子类. 初始化子类静态代码块和成员变量 2.load完成父类与子类后,从main函数入口运行 ...
- Java类成员变量、普通成员变量、初始化块、构造方法的初始化和执行顺序
结论:执行的大致顺序如下, (1) 在一个不存在继承的类中:初始化static变量,执行static初始化块-->初始化普通成员变量(如果有赋值语句),执行普通初始化块-->构造方法 (2 ...
- java 子类的实例化和代码块初始化过程
1,子类的实例化 1,子父类中的构造函数的特点. 在子类构造对象时,发现,访问子类构造函数时,父类也运行了. 为什么呢? 原因是:在子类的构造函数中第一行有一个默认的隐式语句. super(); 子类 ...
- 【转】Java类成员变量默认初始化规则
一个变量作为类成员使用的时候,如果没有被初始化,java会为其分配默认值: -------------------------------------------------------------- ...
- java 类、方法、代码块修饰式关键字总结
super 关键字 this和super的区别 访问成员的区别 this关键字 this特点 this使用场景 static关键字 例子 访问权限修饰符 特点 总结: 四个修饰符的特点 访问权限修饰符 ...
- Java类成员变量的默认值
1.布尔型(boolean)变量默认值为false,byte.short.int.long为0,字符型为'\u0000'(空字符),浮点型(float double)为0.0,引用类型(String) ...
- Delphi会自动初始化全局变量和类成员变量,但不初始化局部变量
If you don't explicitly initialize a global variable, the compiler initializes it to 0. Object insta ...
- Java类的成员之四:代码块.
3.2类的成员之四:代码块 ①初始化块(代码块)作用:对Java对象进行初始化 ②程序的执行顺序: ③一个类中初始化块若有修饰符,则只能被static修饰,称为静态代码块(static block ) ...
- java 面向对象(二十):类的结构:代码块
类的成员之四:代码块(初始化块)(重要性较属性.方法.构造器差一些)1.代码块的作用:用来初始化类.对象的信息2.分类:代码块要是使用修饰符,只能使用static分类:静态代码块 vs 非静态代码块3 ...
随机推荐
- css3多列及瀑布流效果
css3内容分块,多列效果(类似报纸版块排版): .div02{ /*count:内容分为几列,gap:内容与分割线的距离,rule:分割线样式*/ column-count:; column-gap ...
- 腾讯织云:DevOps 流水线应用平台践行之路
欢迎大家前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~ 作者:梁定安,腾讯织云负责人,目前就职于腾讯社交网络运营部,任运维技术总监,开放运维联盟委员,腾讯云布道师,腾讯课堂运维讲师,EXIN D ...
- WebApp开发总结
WebApp开发总结 框架的使用网络上都有教程,就不写了,主要记录下个人的开发总结以方便以后开发注意. css公用样式统一定义 css样式抽出复用 appearance: none; 取消系统默认样式 ...
- Cause: net.sf.cglib.beans.BulkBeanException; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException:
2017-03-13 15:40:15,003 ERROR [com.hisense.hitv.service.dotexc.impl.DotExcPolicyServiceImpl.updateD ...
- OpenPop.NET
OpenPop用于接收邮件,可以读取邮件内容或者邮件附件内容导入到系统中 http://hpop.sourceforge.net/documentation/index.html
- Notepad++使用图解
Notepad++使用图解.. Notepad++的安装部分 -------------- -------------- --------------- -------------- -------- ...
- Kubernetes e2e test and test framework
前言 Kubernetes的成功少不了大量工程师的共同参与,而他们之间如何高效的协作,非常值得我们探究.最近研究和使用了他们的e2e测试和框架,还是挺有启发的. 怎样才是好的e2e测试? 不同的人写出 ...
- Windows下JNI的使用教程
JNI的使用大致有以下4个步骤: 一.在Java中写native方法 二.用javah命令生成C/C++头文件 三.写对应的C/C++程序实现头文件中声明的方法,并编译成库文件 四.在Java中加载这 ...
- python条件判断与循环
条件判断 1.python缩进规则: 如果if语句判断是True,就把缩进的语句执行了,否则,什么也不做,比如: age=20 if age >= 18: print('your age is' ...
- SQL查询语句分类
SQL查询语句有多种,下面总结下.首先先建三张表用于后面的实验 -- 学生表,记录学生信息 CREATE TABLE student( sno ), sname ), ssex ENUM('男','女 ...