代码块(block)
代码块概念
- 在Java中,使用大括号”{}“括起来的代码被称为代码块,根据其位置和声明方式的不同,可以分为:
- 局部代码块
- 构造代码块
- 静态代码块
- 同步代码块(多线程讲解)
- 代码块在实际开发中,使用频率并不高,可替代性也很强
- 但是由于其迷惑性极强,常年出没于各种面试题中
局部代码块(local)
什么是局部代码块?
- 和局部变量位置相似,处在方法中局部位置的代码块,称之为局部代码块
- 声明方式:{}
- 位置:方法中的局部位置
- 代码执行顺序:从上到下
- 作用:限定局部变量的作用范围和生命周期,及早释放,提高内存利用率
- 实际用途:并没有多大用,不要在代码中使用局部代码块
构造代码块(building)
什么是构造代码块
- 和构造方法类似,处在类中成员位置的代码块,称之为构造代码块
- 声明:{}
- 位置:在类中成员位置
- 作用:依赖于构造方法的执行而执行,是在new对象的时候给成员变量进行赋值的,每次new对象都会执行
- new对象过程,构造代码块的执行顺序
- 如果构造器在第一行显式的调用了另一个构造器,那么先执行this构造器
- 否则
- 先把所有成员变量的值默认初始化
- 按照类中定义代码块和成员变量的位置,从上到下执行代码块和成员变量自身的初始化语句
- 最后执行该构造器代码
- 需要注意的是:
- 应该永远将构造代码块,放在成员变量的定义语句下面
- 一方面,如果代码块初始化在上,成员变量声明在下,逻辑上会很奇怪
- 另一方面,如果对象的创建依赖于代码块和成员变量的定义位置,很容易引发错误
- 可以使用this关键字,但是意义不大
- 应该永远将构造代码块,放在成员变量的定义语句下面
- 实践用途:
- 构造器只是创建某一个对象时调用的,但构造代码块却是创建该类每个对象都会调用的
- 因此,可以抽取出所有构造器都需要做的事情,放入构造代码块中
静态代码块
什么是静态代码块
- 使用static关键字修饰的构造代码块,处在类中的成员位置,称之为静态代码块
- 声明:static{}
- 位置:类中成员位置
- 作用:和静态成员一样,随着类加载而执行,一般用于给静态成员变量赋值,只执行一次
- new对象过程,静态代码块、构造代码块、构造方法的执行顺序
- 静态代码块
- 构造代码块
- 构造方法
- 需要注意的是:
- 静态代码块和静态成员一样,不能在里面调用非静态
- 除非是静态成员变量需要很复杂的初始化代码,否则没太大必要使用,直接显式赋值就行
- 静态代码块和静态成员变量的定义顺序,也会影响到静态成员变量的最终取值
- 所以应该永远将静态代码块放在静态成员变量的定义下面
- 构造代码块可以给静态成员变量赋值,静态代码块却不能给普通成员代码块赋值
- 若构造代码块和静态代码块同时给一个静态成员变量赋值
- 它们在代码中的顺序,并不会对结果造成影响
- 因为静态代码块总是先于构造代码块执行
- 若构造代码块和静态代码块同时给一个静态成员变量赋值
一定会触发类加载的几种情况
- 执行某个类的main方法,一定会进行 类加载
- 创建某个类的对象,一定会进行类加载
- 访问某个类的静态成员,一定会进行类加载
- 当静态成员变量为final修饰时,访问该成员变量不进行类加载
- 当静态成员方法为final修饰时,访问该成员方法会进行类加载
牛刀小试
查看以下代码,请回答程序运行的结果
public class ExerciseBlock {
static {
System.out.println("静态代码块!");
}
{
System.out.println("构造代码块!");
}
public static void main(String[] args) {
System.out.println("main方法开始执行!");
Star s = new Star();
System.out.println(Star.name);
}
}
class Star{
static String name;
{
Star.name = "杨超越";
System.out.println("我喜欢杨超越");
}
static {
name = "杨幂";
System.out.println("我喜欢杨幂");
}
public Star() {
System.out.println("Satr:构造器!");
}
}
- 程序的打印结果应该什么呢?
- 为什么?