public AllKindsSort() {
System.out.println("helloA");
}
{
System.out.println("I am AllKindsSort");
}
static {
System.out.println("I am static AllKindsSort");
}
}
public class BllKindsSort extends AllKindsSort {
public BllKindsSort() {
System.out.println("helloB");
}
{
System.out.println("I am BllKindsSort");
}
static{
System.out.println("I am static BllKindsSort");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("-----main start-------");
new BllKindsSort();
new BllKindsSort();
System.out.println("------main end--------");
}
}
运行结果:
I am static AllKindsSort
I am static BllKindsSort
-----main start-------
I am AllKindsSort
helloA
I am BllKindsSort
helloB
I am AllKindsSort
helloA
I am BllKindsSort
helloB
------main end--------
类的生命周期是从被加载到虚拟机内存中开始,到卸载出内存结束。过程共有七个阶段,其中到初始化之前的都是属于类加载的部分
加载----验证----准备----解析-----初始化----使用-----卸载
1、加载阶段
这个流程中的加载是类加载机制中的一个阶段,这两个概念不要混淆,这个阶段需要完成的事情有:
1)通过一个类的全限定名来获取定义此类的二进制字节流。
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。
3)在java堆中生成一个代表这个类的Class对象,作为访问方法区中这些数据的入口。
2、准备阶段
这个阶段正式为类变量(被static修饰的变量)分配内存并设置类变量初始值,这个内存分配是发生在方法区中。
1、注意这里并没有对实例变量进行内存分配,实例变量将会在对象实例化时随着对象一起分配在JAVA堆中。
2、这里设置的初始值,通常是指数据类型的零值。
private static int a = 3;
这个类变量a在准备阶段后的值是0,将3赋值给变量a是发生在初始化阶段。
3、初始化阶段
初始化是类加载机制的最后一步,这个时候才正真开始执行类中定义的JAVA程序代码。在前面准备阶段,类变量已经赋过一次系统要求的初始值,在初始化阶段最重要的事情就是对类变量进行初始化,关注的重点是父子类之间各类资源初始化的顺序.
初始化的步骤
1、如果该类还没有加载和连接,则程序先加载该类并连接。
2、如果该类的直接父类没有加载,则先初始化其直接父类。
3、如果类中有初始化语句,则系统依次执行这些初始化语句。
在第二个步骤中,如果直接父类又有直接父类,则系统会再次重复这三个步骤来初始化这个父类,依次类推,JVM最先初始化的总是java.lang.Object类。当程序主动使用任何一个类时,系统会保证该类以及所有的父类都会被初始化。
分析上述3个步骤,我们可以得出例子的运行结果:
1.加载阶段:做基础准备工作
2.准备阶段:为静态语块分配内存(静态区),只执行一次,为最先执行的代码.
3.初始化阶段:创建子类,要先初始化父类.先初始化父类非静态代码,然后执行父类构造方法,执行子类非静态代码块,再执行那个子类构造方法.