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、执行子类的构造函数

父类静态代码块
子类静态代码块
父类代码块
父类构造
子类代码块
子类构造