Java学习笔记-初始化

静态数据的初始化

静态数据初始化的几个原则:

  • 次数】无论创建多少个对象,静态数据只初始化一次
  • 【时机】静态初始化只有在必要时刻才会进行。只有在第一次访问静态数据或静态域时,才会初始化
  • 【与是否创建对象无关】当加载类时,就会初始化静态对象,无论是否创建该类对象
  • 【顺序】当静态与非静态对象共存时,先初始化静态对象

值得注意的是,非静态对象也会在构造函数之前初始化

举例代码如下

//: initialization/StaticInitialization.java
// Specifying initial values in a class definition.
import static net.mindview.util.Print.*;

class Bowl {
  Bowl(int marker) {
    print("Bowl(" + marker + ")");
  }
  void f1(int marker) {
    print("f1(" + marker + ")");
  }
}

class Table {
  static Bowl bowl1 = new Bowl(1);
  Table() {
    print("Table()");
    bowl2.f1(1);
  }
  void f2(int marker) {
    print("f2(" + marker + ")");
  }
  static Bowl bowl2 = new Bowl(2);
}

class Cupboard {
  Bowl bowl3 = new Bowl(3);
  static Bowl bowl4 = new Bowl(4);
  Cupboard() {
    print("Cupboard()");
    bowl4.f1(2);
  }
  void f3(int marker) {
    print("f3(" + marker + ")");
  }
  static Bowl bowl5 = new Bowl(5);
}

public class StaticInitialization {
    //加载StaticInitialization类时,即开始初始化static对象,也就是table和cupboard
  public static void main(String[] args) {
    print("Creating new Cupboard() in main");

      // 再次生成Cupboard对象,但是此时静态对象已经加载过一遍
      // 所以只会在调用构造函数前生成bowl3
    new Cupboard();
    print("Creating new Cupboard() in main");
    new Cupboard();
    table.f2(1);
    cupboard.f3(1);
  }

    // 初始化table对象,加载Table类
    // 由于是第一次加载Table类,所以会初始化Table.bowl1 对象
    // 然后初始化下一个static对象,Table.bowl2
    // static对象都初始化以后,调用构造函数Table()
  static Table table = new Table();

    // 由于静态对象先于非静态对象,所以先初始化bowl4,bowl5
    // 值得注意的是,非静态对象也会在构造函数之前初始化(bowl3)
  static Cupboard cupboard = new Cupboard();
}
 /* Output:
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)
*///:~

继承与初始化

与C艹不同,java中所有事物都是对象。也就是说,每个类的编译代码都在自己独立文件中,只有在需要使用程序时才会加载,而不是像C++这样按顺序加载的。

当程序中有继承存在时,会按照继承关系依次加载所有相关的类。自然的,也会初始化各父类中的静态变量。当父类中的静态变量初始化完毕以后,子类中的静态变量才会开始加载。(但在生成对象之前,不会初始化非静态变量)

一般来说,初始化的顺序是:

父类静态变量初始化 -> 子类静态变量初始化
-> 父类非静态变量初始化 -> 父类构造函数
-> 子类非静态变量初始化 -> 子类构造函数

前两个环节无论生不生成对象,都会执行。
后四个环节只有在生成对象时才会执行

//: reusing/Beetle.java
// The full process of initialization.
import static net.mindview.util.Print.*;

class Insect {
  private int i = printInit("i is initialized");
  protected int j;
  Insect() {
    print("i = " + i + ", j = " + j);
    j = 39;
  }
  private static int x1 =
    printInit("static Insect.x1 initialized");
  static int printInit(String s) {
    print(s);
    return 47;
  }
}

public class Beetle extends Insect {
    // 找到Beetle类的编译代码以后,发现有一个基类,所以需要先加载基类
    // 首先初始化Insect中的 x1,然后初始化Beetle.x2 (只初始化静态变量)
    // 此时必要的类已加载完毕,可以执行main函数
  private int k = printInit("Beetle.k initialized");
  public Beetle() {
    print("k = " + k);
    print("j = " + j);
  }
  private static int x2 =
    printInit("static Beetle.x2 initialized");
  public static void main(String[] args) {
    print("Beetle constructor");

      // 开始创建beetle对象
      // 但是由于beetle继承自insect类,所以要先对insect类进行初始化
      // 对于任何一个类,生成对象的顺序都是 静态变量初始化->非静态变量初始化->构造函数
    Beetle b = new Beetle();
  }
} 
/* Output:
static Insect.x1 initialized
static Beetle.x2 initialized
Beetle constructor
i = 9, j = 0
Beetle.k initialized
k = 47
j = 39
*///:~
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值