在Java中代码块指的是使用”{}”括起来的代码称为代码块。代码块一共分为4种:局部代码块,静态代码块,同步代码块,构造代码块。html
局部代码块就是定义在方法体内部的代码块。多线程
public class CodeBlockTest { public static void main(String[] args) { int i; { i=10; System.out.println("局部代码块"+i); int j=20; System.out.println("局部代码块"+j); } System.out.println(i); //Cannot resolve symbol 'j' //System.out.println(j); } }
能够看到,在局部代码块中声明的变量,只能在局部代码块中进行访问。局部代码块能够操做非局部代码块的变量,可是非局部代码块不能访问局部代码块的变量。这就起到了很好的分隔,就能够用来限制局部变量的生命周期,及早释放,提升内存利用率。若是有多个局部代码块,则按照它们定义的前后顺序执行。函数
静态代码块就是在类中用static关键字修饰的代码块,它不能出如今方法体或者代码块内,我在上一篇的Static关键字中也记录了静态代码块的使用,因此就把那里的例子引用过来了。spa
被static修饰的代码块也叫静态代码块,会随着JVM加载类的时候而加载这些静态代码块,而且会自动执行。它们能够有多个,能够存放在于该类的任何地方(不能放在方法内部)。JVM会按照它们的前后顺序依次执行它们,并且每一个静态代码块只会被初始化一次,不会进行屡次初始化。线程
简单示例:3d
public class Person{ static { System.out.println("Person类静态块"); } public Person() { System.out.println("Person类构造器"); } public static void main(String[] args) { new Son(); System.out.println("-------"); new Son(); } } class Son extends Person{ static { System.out.println("Son类静态块"); } public Son() { System.out.println("Son类构造器"); } }
运行结果:code
从运行结果分析:首先运行main()方法,而后JVM就会加载类,由于Son类继承了Person类,因此会先加载父类Person类,再去加载子类Son。因为静态代码块会随着类的加载而加载,因此先输出父类中静态代码块内容"Person类静态块",而后输出子类中静态代码块内容"Son类静态块"。加载完类以后执行main()方法内容,先new了第一个Son实例,因为子类构造器中默认调用了super(),因此先输出父类构造器的内容,再输出子类构造器的内容。以后又new了第二个Son实例,倒是输出的构造器的内容,说明static静态块只加载了一次。结论:静态代码块是先加载父类的静态代码块,而后再加载子类静态代码块,是随着类的加载而加载,并且只会加载一次。htm
补充:由于入口main()是个方法,也须要用类去调用,因此类的加载优先级>main()方法。对象
是使用synchronized关键字修饰的普通代码块(其只能用在方法内部)。其做用在多线程的环境下,对共享数据进行加锁, 从而实现线程同步,是一种多线程保护机制。blog
public void show(){ synchronized (obj){ System.out.println("同步代码块"); } }
直接在类中用"{}"定义且不加任何关键字的代码块成为构造代码块。
public class CodeBlockTest { { System.out.println("构造代码块..."); } public CodeBlockTest() { System.out.println("无参构造器..."); } public static void main(String[] args) { new CodeBlockTest(); new CodeBlockTest(); } }
运行结果:
从运行结果容易看出,在建立对象时,构造代码块才会被执行,并且优先于构造方法执行(这里和构造块写前写后不要紧,将构造块写在构造方法后面也是同样的结果)。并且每当有对象被建立的时,都会执行构造代码块。若是存在多个构造代码块,则执行顺序按照定义顺序依次执行。
构造代码块的做用:能够用来初始化实例变量和实例环境(即建立对象的必要条件),这样不只能够减小代码量,同时也能够加强程序的可读性。
注意:构造代码块并非真正的在构造方法以前执行的,JVM在编译的时候会把构造代码块插入到每一个构造函数的最前面,构造代码块随着构造方法的执行而执行,若是某个构造方法调用了其余的构造方法,那么构造代码块不会插入到该构造方法中以避免构造代码块执行屡次。咱们能够从编译生成的class文件能够看出来。
上面讲述了四种代码块的基本信息,而后咱们来看一下四种代码块的执行顺序。
public class CodeBlockTest { static { System.out.println("静态代码块..."); } { System.out.println("构造代码块..."); } public CodeBlockTest() { System.out.println("无参构造器..."); } public void show(){ { System.out.println("局部代码块..."); } } public static void main(String[] args) { System.out.println("main()方法运行"); new CodeBlockTest().show(); System.out.println("----------"); new CodeBlockTest().show(); } }
打印结果:
执行顺序(优先级从高到低):静态代码块>mian()方法>构造代码块>构造方法>局部代码块。其中静态代码块只执行一次。构造代码块和局部代码块再每次建立对象是都会执行。