08、初始化块 -- 成员变量初始化

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("子类 -- 构造器"); }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值