- 非静态变量初始化:
(1)类的基础数据类型变量不对其初始化,运行时不会报错,因为编译器会为此变量赋一个初始值;而对象的引用变量如果不初始化,此引用为null,运行时会报“NullPointerException”。
(2)方法的中的变量(即局部变量)不管是基础数据类型还是对象的引用,如果不初始化,编译时就会报错。 - 静态初始化:
类首次加载到内存时会完成类的静态变量的初始化。 - 构造器初始化:
构造初始化之前会先初始化类的非静态变量,然后在对象被操作之前构造完成初始化。
初始化顺序:
静态变量(包括静态块)> 非静态变量(包括非静态块) > 构造器
下面做个简单的测试:
打印如下:
I am father’s static!
I am son’s static!
I am father!
This is father’s constructor!
I am son!
This is son’s constructor!
分析:
1、在main中new了一个Son的对象,这时候就需要加载Son类,而Son继承于Father,故而先加载Father类到内存中。
2、静态变量是在类的第一次加载时初始化,所以首先打印“I am father’s static!”。
3、Father类加载完后,继续加载Son类,同理,打印“I am son’s static!”。
4、Father类和Son类加载完后,接下来进行的是实例化。
5、由于Son类继承于Father类,子类的对象要想获得父类的属性,必须先要实例化父类。
6、调用Father类的构造之前,先初始化Father类的变量和非静态代码块,打印出“I am father!”,然后调用构造打印出“This is father’s constructor!”。
7、实例化Son类,同6,先后打印出“I am son!”和“This is son’s constructor!”。
初始化扩展
类的加载:java程序的各个部分时在必须时才加载的(动态加载)。类加载时,类加载器会首先检查这个类Class对象是否已经加载,如果尚未加载,根据类名查找.class文件。
人为加载类并获取该类的Class对象的引用有两种方式:.class和classForName()
区别在于:使用.class来获取类的Class对象的引用不会引发初始化,而classForName()会引发初始化。
(注意:“static final int i= 23”这种编译期常量不需要类进行初始化时就可以被读取。)