1、初始化块的定义
- 语法:
[修饰符]{
// 可执行性的语句。
}
- 修饰符 : 只能出现 static
- 有 static,说明它是 类初始化块 / 静态初始化块。
- 无 static,说明它是 实例初始化块 / 非静态初始化块。
- 由于初始化块 没有名字。所以,它只能被 “隐式”执行。
2、实例初始化块 何时被执行?
- 实例初始化块的代码,会在【每次调用构造器之前】被隐式执行。
- 规则:【位于构造器之前】的,而且【无需传入参数】的代码就可被提取到初始化块内 。
- 实例初始化块和构造器的作用几乎是相同的,但实例初始化块的优先级更高。
- 实例初始化块包含的代码,总是在构造器包含的代码之前执行。
- 1、源码:
public class User implements Serializable {
private String name;
private Short age;
{
name = "张三";
age = 10;
System.out.println("非静态初始化块!!!");
}
// 无参数构造器
public User() {
}
// 有参数构造器
public User(Short age, String name) {
this.age = age;
this.name = name;
// 可以有 return 语句。但是 return 后边不能有 返回值。
return;
}
public static void main(String[] args) {
User user = new User((short) 30, "张三");
System.out.println(user);
}
}
- 2、class 文件反编译之后的代码:
- 实例初始化块包含的代码,总是在构造器包含的代码之前执行。
public class User implements Serializable {
// 实例初始化块中,为成员变量赋值语句,直接变成,声明变量后,直接赋值。
private String name = "张三";
private Short age = Short.valueOf((short)10);
// 有参数构造器
public User() {
System.out.println("非静态初始化块!!!");
}
// 有参数构造器
public User(Short age, String name) {
System.out.println("非静态初始化块!!!");
this.age = age;
this.name = name;
}
public static void main(String[] args) {
User user = new User(Short.valueOf((short)30), "张三");
System.out.println(user);
}
}
- 3、查看字节码文件
- 在编译的时候:
- JDK 编译器会把【实例初始化块的代码】,【声明 field 时候指定初始值的代码】都提取出来,并【插入】到构造器的最前面。
- 按【实例初始化块的代码】与【声明 field 时候指定初始值的代码】在代码中先后顺序执行的。
3、静态初始化块 / 类初始化块 / 静态代码块 何时被执行?
- 类初始化块
- 在类加载时,执行 静态代码块 以及 完成 类变量 的 显式初始化 工作。
- 一个JVM,对一个类,只初始化一次,因此类初始化只有一次机会。
- 当程序第一次【主动】使用该类就会初始化该类》如下:
- 访问了该类静态的 Field 或 静态方法。
- 初始化了该类的子类。 – Java初始化一个类。永远先从最顶层父类开始初始化。
- 使用反射来 Class.forName (类名字符串)。
- 如果该类作为主类使用 (有 main 方法,而且程序确实从该 main 方法开始执行)。
- 使用该类创建对象。
- 典型的:使用类来声明变量,并不算主动使用该类。
4、静态初始化块和 main 方法哪个先被执行?
- 静态初始化块先执行。
5、语句块能否使用外部的变量?语句块中定义的变量,外部能否使用?
- 语句块能使用外部的变量。
- 但是语句块中定义的变量外部不能使用
6、继承 – 静态初始化块、非静态初始化块、构造器 间的执行顺序是什么样的?
public class OrderExecOrder {
static { System.out.println("调用类 -- 静态初始化块"); }
{ System.out.println("调用类 -- 非静态初始化快"); }
public static void main(String[] args) {
System.out.println("调用类 -- main 方法");
new SubClass();
/*
执行顺序
调用类 -- 静态初始化块
调用类 -- main 方法
父类 -- 静态初始化块
子类 -- 静态初始化块
父类 -- 非静态初始化快
父类 -- 构造器
子类 -- 非静态初始化快
子类 -- 构造器
*/
}
}
class SuperClass {
static { System.out.println("父类 -- 静态初始化块"); }
{ System.out.println("父类 -- 非静态初始化快"); }
SuperClass(){ System.out.println("父类 -- 构造器"); }
}
class SubClass extends SuperClass {
static { System.out.println("子类 -- 静态初始化块"); }
{ System.out.println("子类 -- 非静态初始化快"); }
SubClass(){ System.out.println("子类 -- 构造器"); }
}