类的初始化顺序与主动引用细节(关于类的生命周期,详见参考文献)
/** * Project Name:thinkinginjava * File Name:Beetle.java * Package Name:com.sourcecode.java.util * Date:2016年2月20日下午12:14:22 * Copyright (c) 2016, [email protected] All Rights Reserved. * */ package com.sourcecode.java.util; /** * ClassName: Beetle <br/> * Reason: TODO 类的生命周期之类的初始化与主动引用 <br/> * 构造方法:隐性的静态方法-没有显性申明static关键字 * 方法(包括构造方法)的执行总是在变量的初始化执行之后: * 1、变量l = setValue(str) 后,再执行构造方法Beetle()) * 2、执行main方法前,先初始化staticfield * * date: 2016年2月20日 下午12:14:22 <br/> * @author Ivy Peng * @version 1.0 * @since JDK 1.6 */ public class Beetle extends Insect { private int k = initialize("Beetle's field k initialized with static initializer!"); private int l = setValue("Beetle's field l initialized with non-static initializer!!"); private String str; Beetle() { System.out.println("In Beetle's constructor!"); System.out.println("k = "+k+",j = "+j+",l = " +l +",str = " + str); } /** * @param string Value to be set * @return Value * @since JDK 1.6 */ private int setValue(String string) { System.out.println(string); return 66; } private static int staticfield = initialize("Beetle's static field nitialzied!"); /** * TODO 测试.<br/> */ public static void main(String[] args) { System.out.println("In Beetel's main()"); Beetle beetle = new Beetle(); } } class Insect { private int i =18; protected int j ; Insect() { System.out.println("In Class Insect's Insect() constructor!"); System.out.println("i = " + i + ",j = " +j); this.j = 28; } private static int staticfield = initialize("Insect's staticfield initialized success!"); static int initialize(String info) { System.out.println(info); return 8; } }
Insect's staticfield initialized success! Beetle's static field nitialzied! In Beetel's main() In Class Insect's Insect() constructor! i = 18,j = 0 Beetle's field k initialized with static initializer! Beetle's field l initialized with non-static initializer!! In Beetle's constructor! k = 8,j = 28,l = 66,str = null
这里以实验中的具体案例加以说明
程序执行-> 访问main方法 -> 导致类的字节码Beetle.class被加载-> 加载过程中发现extends关键字 -> 导致父类Insect.class被加载。
验证:当一个类被加载之后,必须要验证一下这个类是否合法,比如这个类是不是符合字节码的格式、变量与方法是不是有重复、数据类型是不是有效、继承与实现是否合乎标准等等。总之,这个阶段的目的就是保证加载的类是能够被jvm所运行。
准备:准备阶段的工作就是为类的静态变量分配内存并设为jvm默认的初值,对于非静态的变量,则不会为它们分配内存
解释:把常量池中的符号引用转换为直接引用。
初始化父类Insect的静态资源(Insect.staticfield = 8)-> 初始化子类Beetle的静态资源(Beetle.staticfield = 8).
以上完成了类的初始化 :->为Beetle对象的诞生做了必要的准备 ->原始变量k、l值置0;引用变量str置null
->原始变量i、j 值置0(引用变量如果有的话置null,这里没有)-> 调用父类的构造方法Insect()
->Insect()方法体执行完成
-> Beetle()方法体执行完成 -> 至此类Beetle的对象beetle实例化完成
-> 准备吃饭客
注:红色标注的地方有待验证-到底是先初始化i,j的值为0,然后调用Insect(),还是先Insect(),然后置i,j = 0呢?个人偏向前者。
1. 《thingking in java》 by Bruce Eckel.
2. 类的生命周期:http://blog.csdn.net/pengych_321/article/details/50704284