初始化块是java类里可出现的第四种成员变量(前面依次是成员变量,方法,构造器),一个类里可以有多个初始化块,相同类型的初始化块之间执行顺序为顺序执行:即前面定义的初始化块先执行,后面定义的初始化块后执行。
初始化块有两种:没有修饰符的普通初始化块以及带static修饰符的静态初始化快。
{
//初始化块
}
static{
//类初始化快
}
package project1;
import org.junit.Test;
public class test {
public int a = 10;
static {
// 静态初始化代码..
/**
* 定义初始化块时候,使用了static修饰符,又叫类初始化快
* 普通初始化块负责对对象执行初始化,类初始化块负责对类进行初始化。
* 系统将在类初始化阶段执行静态初始化块,而不是在创建对象时候,所以静态初始化块总是比普通初始化块先执行
* 静态初始化块也属于静态成员,因此需要遵循静态成员不能访问非静态成员的规则。
* 执行一次,在加载类时候被执行,不再被执行。
*/
System.out.println("类初始化模块");
}
{
// 普通初始化代码..
/**
* 初始化块没有名字,没有标识,因此无法通过类,对象来调用初始化。 初始化块只会在创建java时候隐式执行,在构造器之前执行。
* 相同类型的初始化块,会顺序执行。
* 从某种程度来说,初始化块是构造器的补充,初始化器总是在构造器之前执行。
* 系统同样可以用初始化块来进行对象的初始化操作
* 与构造器不同的是,初始化块是一段固定的执行的代码,且不能接受任何参数,对同一个类中的所有对象进行的初始化操作都相同
*
*
*/
a = 25;
System.out.println("初始化模块1");
}
{
a = 19;
System.out.println("初始化模块2");
}
public test() {
System.out.println("无参构造函数");
}
@Test
public void method1() {
System.out.println();
test t1 = new test();
System.out.println("*************************");
test t2=new test();
}
}
构造函数、非静态初始化块、静态代码块都是用于初始化,三者的执行顺序依次是:静态代码块>初始代码块>构造函数。
三者都用于初始化,静态初始化是在类加载时候,初始代码块是在创建对象时候,构造函数是new创建对象时候。初始代码块跟构造函数区别是,初始代码块跟静态代码块都是一段固定执行的代码,不能接受任何参数,因此我们不难发现代码块的基本用法,如果有一段初始化处理的代码,对所有对象相同且不需要接受任何参数,就可以吧这段代码提取到代码块中。通过把多个构造器中的相同代码提取到初始化块中定义,能更好的提高初始化代码的复用,提高整个应用的可维护性。
需要注意的是,对与同是的初始化代码块或者静态代码块,执行顺序是顺序执行,先写的先执行,后面的后执行,对于相同的属性赋值,会有覆盖。静态初始化实例,只能初始化静态方法或者实例。
初始化代码块(不是静态代码块),其实是个假象,使用javac命令编译java类后,该java类中的初始化块会消失--初始化代码块会被还原到每个构造器中,且位于构造器所有代码的前面。静态初始化代码块只执行一次,并长期存在jvm中,以为当第一次使用类时候,初始化类时候调用静态代码块,类就会在jvm中长期存在,当再次创建该类实例时候,不会再次初始化类,而是调用虚拟机里面存储的,所以静态代码块只执行一次。