java中静态变量,静态代码块,静态方法,实例变量,匿名代码块的加载顺序
1 普通代码块
就是类中方法的方法体
public void xxx(){
//code
}
2 构造块
用{}裹起来的代码片段,构造块在创建对象时会被调用,每次创建对象时都会被调用,并且优先于类构造函数执行。 构造块中定义的变量是局部变量。
{
//code
}
3 静态块
static{
//code
}
4 同步代码块
使用synchronized(obj){}裹起来的代码块,在多线程环境下,对共享数据进行读写操作是需要互斥进行的,否则会导致数据的不一致性。常见的是synchronized用来修饰方法,其语义是任何线程进入synchronized需要先取得对象锁如果被占用了,则阻塞,实现了互斥访问共享资源。而synchronized也是有代价的。一个常见的场景是,一个冗长的方法中,其实只有一小段代码需要访问共享资源,这时使用同步块,就只将这小段代码裹在synchronized block,既能够实现同步访问,也能够减少同步引入的开销。 同步代码块须写在方法中。
synchronized(obj){
//code
}
5 实例
public class Test { //1.第一步,准备加载类
public static void main(String[] args)
{
new Test(); //4.第四步,new一个类,但在new之前要处理匿名代码块
// 这里必须等待类加载完
System.out.println("done..");
Test.run();
}
static int num = 4; //2.第二步,静态变量和静态代码块的加载顺序由编写先后决定
static
{
System.out.println("num:"+num); // 3.第三步,静态块,然后执行静态代码块,因为有输出,故打印a
System.out.println("a");
}
{
num += 3;
System.out.println("b:"+num); //5.第五步,按照顺序加载匿名代码块,代码块中有打印
}
int a = 5; //6.第六步,按照顺序加载变量
{ // 成员变量第三个
System.out.println("c:"+a); //7.第七步,按照顺序打印c
}
Test() { // 类的构造函数,第四个加载
System.out.println("d"); //8.第八步,最后加载构造函数,完成对象的建立
}
static void run() // 静态方法,调用的时候才加载
{
System.out.println("e");
}
}
运行:
num:4
a
b:7
c:5
d
done..
e
一般顺序:静态块(静态变量)——>成员变量——>构造方法——>静态方法
1、静态代码块(只加载一次)
2、构造方法(创建一个实例就加载一次)
3、静态方法需要调用才会执行
如果类还没有被加载:
1、先执行父类的静态代码块和静态变量初始化,并且静态代码块和静态变量的执行顺序只跟代码中出现的顺序有关。
2、执行子类的静态代码块和静态变量初始化。
3、执行父类的实例变量初始化
4、执行父类的构造函数
5、执行子类的实例变量初始化
6、执行子类的构造函数
父类静态代码块
子类静态代码块
父类代码块
父类构造
子类代码块
子类构造