java -- 变量初始化顺序

1. 引言

在一个的 java 程序中,为了保证程序的健壮性,在初始化一个对象之前, 应该保证对象中的变量都有进行初始化的操作。那么,在对象初始化过程中,变量加载的顺序大致是怎么样的呢?这篇文章主要探讨这个问题,包含普通变量静态变量静态代码块 的加载顺序。

2. 普通变量

在类中,变量定义位置的先后会影响到它们的加载顺序,但是,无论如何,它们都会在构造方法执行之前进行初始化,我们来看下面这段代码:

首先创建一个 Book 类,只定义一个有参的构造方法:

public class Book {
    public Book(int i){
        System.out.println("book" + i +" init ...");
    }
}

接着创建一个 BookStore 类,该类中有两个 Book 类的引用,并进行了初始化。注意,这边有意将 book2 写在 book1 上。

public class BookStore {
    public Book book2 = new Book(2);
    public Book book1 = new Book(1);

    public BookStore(){
        System.out.println("bookstore init ...");
    }
}

最后,在 main 创建一个 BookStore 对象:

public class MainApp {
    public static void main(String[] args){
        BookStore bookStore = new BookStore();
    }
}

最终运行结果如下,从结果可以看出,由于 book2 变量定义在 book1 之前,根据类加载普通变量的顺序,所以在加载时它在 book1 之前。

book2 init …

book1 init …

bookstore init …

3. 静态变量初始化

为了验证静态变量是在什么时候初始化的,我们在 BookStore 中添加一个 static 变量。

public class BookStore {
    public Book book2 = new Book(2);
    public Book book1 = new Book(1);

    public static Book book3 = new Book(3);

    public BookStore(){
        System.out.println("bookstore init ...");
    }
}

在 MainApp 中对 BookStore 进行两次初始化:

public class MainApp {
    public static void main(String[] args){
        BookStore bookStore = new BookStore();
        bookStore = new BookStore();
    }
}

运行结果如下,我们可以看出,static 变量在 book1、book2 这两个变量之前进行加载,说明 static 变量是一个类中最先进行初始化的。

之后,MainApp 中又进行了一次初始化,而此时 book3 并没有重新进行加载,说明静态变量只会在第一个 Book 创建时才会进行初始化,之后,静态变量不会再进行初始化操作了。

book3 init …
book2 init …
book1 init …
bookstore init …
book2 init …
book1 init …
bookstore init …

4. 静态代码块

java 中允许将多个静态初始化动作组织成一个特殊的 “静态语句”(有时也叫”静态块“),例如下面这个样子:

public class Test{
    int i;
    static{
        i = 4;
    }
}

静态代码块加载的顺序和静态变量加载规律一样,这里就不再进行重复说明。需要注意的是,当静态代码块碰到静态变量时会怎样呢?这就跟普通变量加载顺序是一致的,位置先后影响他们初始化的顺序,这个可以自行做实验进行验证。

5. 总结

通过上面几个简单的小实验,在这里总结一下对象的创建过程,这一部分主要是参考 《java 编程思想》第四版的内容。

我们在加载 Book 类时,

  1. 即使没有直接标明 static 关键字,构造器实际上也是静态方法。因此,当首次创建类型为 Book 的对象时,或者 Book 的静态变量 / 方法(包括构造方法)首次被访问时,Java 解释器必须查找类路径,以定位 Book.class 文件。
  2. 然后载入 Book.class,有关静态初始化的所有动作都会执行,因此,静态初始化只在 Class 对象首次被加载时进行一次。
  3. 当使用 new Book() 创建对象时,首先将在堆上为 Book 对象分配足够的空间
  4. 这块存储空间会被清零,所有基本数据类型设置为默认值(如 int、float 被设置为 0),引用类型被置为 null
  5. 执行所有出现于字段定义处的初始化动作
  6. 执行构造器。如果涉及继承时,这会牵涉到很多动作。

以上就是一个对象加载变量的顺序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值