java编程思想-initialization and class loading

class code is loaded at the point of first use.

  • 1. the first object of that class is constructed.
  • 2. static field or static methods is accessed.
  • 3. static initialization block take places. (按照在class definition中书写的顺序(texture order)依次load)

class load 和初始化的顺序:

1. class A loaded.
2. base class B will be found and loaded if A has one.
3. base class C will be found and loaded if B has one.
                                                                                                 
4. root class C static initialization.
5  class B static initialization.
6. class A static initialization.
                                                                                                 
7. root class C constructor called.
8. primitives in object are set to 0 & object references in this object are set to null.
9. class C instance values are initialized in texture order.(like this: private int  i = 9;) & rest of C constructor.
10. B preformes 7 - 9
11. A performes 7 - 9
 
恩,想了想,这里还是添加一下具体的解释:

part 1 加载
        当我们使用class A 的时候,根据class code is loaded at the point of first use 的原则,class A会被加载到jvm中。这时候,如果jvm发现A有超类B,那么就会去需找B并加载到jvm中,同样如果B还有超类C,那么超类C也会被找到并load。我们知道,所有java类都有一个默认的超类Object,那么最终Object类会被load到jvm中。
        因此,class load部分的顺序是:A - B - C - Obejct
part 2 静态变量初始化
        所有的class加载完成后,就开始静态变量的实例化。这里首先从root class开始,即Object的静态变量初始化,然后执行C的静态变量的初始化,然后是B,最后才是A。并且静态变量只会初始化一次,如果在超类中有变量static初始化,而子类继承了这个protected field,那么子类使用时不会再次初始化了。第二次建立对象的时候,不会再执行初始化static变量的代码了,这点需要注意一下!
      也许比较难以理解,还是看个例子吧:
public class Insect {
	protected static int i = 10;
	public Insect() {
		System.out.println("Insect.i = " + i);
	}
}
public class Beetle extends Insect {
	public Beetle() {
		System.out.println("Beetle.i = " + i); // 这里会直接继承父类已经初始化完成的static field, 输出10
		System.out.println("Beetle.i = " + i);
	}
	public static void main(String[] args) {
		Beetle b = new Beetle();
	}
}

public class Insect {
	protected static int i = 10;
	public Insect() {
		System.out.println("Insect.i = " + i);
	}
}
public class Beetle extends Insect {
    private int i = 20;
	public Beetle() {
		System.out.println("Beetle.i = " + super.i); // 这里会直接继承父类已经初始化完成的static field, 输出10
		System.out.println("Beetle.i = " + i); // 由于子类的private变量覆盖了父类的变量,因此这里访问到的是子类的i,输出20
	}
	public static void main(String[] args) {
		Beetle b = new Beetle();
	}
}

part 3 构造器调用
        首先调用obejct的构造器,然后最先进行的是实例变量的初始化工作,即类似这样的表达式执行: private int i = 10;如果有多个,则按照texture order编码书写顺序依次执行,这部分工作完成之后,才开始构造器中的代码的真正执行。
然后是C - B - A按照前述的方法依次执行自己的构造器,最终A对象完成全部初始化工作。

如果下面的例子能够理解的话,这部分就算弄明白了
class Insect {
	private int i = 9;
	protected int j;
	Insect(){
		System.out.println("i = " + i + ",j = " + j);
		j = 39;
	}
	private static int x1 = printInt("static Insetct.x1 initialized.");
	static int printInit(String s){
		System.out.println(s);
		return 47;
	}
}

public class Beetle extends Insect {
	private int k = printInit("Beetle.k initialized.");
	public Beetle(){
		System.out.println("k = " + k);
		System.out.println("j = " + j);
	}
	private static int x2 = printInit("static Beetle.x2 initialized.");

	public static void main(String[] args){
		System.out.println("Beetle constructor.");
		Beetle b = new Beetle();
	}
}

/* Output:
static Insetct.x1 initialized. load完成,处于static阶段,会执行所有的static,包括main
static Beetle.x2 initialized.
Beetle constructor.
i = 9,j = 0 (i有在定义时赋予了初始值,而j没有被jvm自动初始化为0)
Beetle.k initialized. (这里才执行到了子类的构造函数)
k = 47
j = 39 (j从父类Insect中继承而来,父类构造函数已经将其初始化为39)
*/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值