1、虚拟机在首次加载Java类时,会对静态初始化块、静态成员变量、静态方法进行一次初始化
2、只有在调用new方法时才会创建类的实例
3、类实例创建过程:按照父子继承关系进行初始化,首先执行父类的初始化块部分,然后是父类的构造方法;再执行本类继承的子类的初始化块,最后是子类的构造方法
4、类实例销毁时候,首先销毁子类部分,再销毁父类部分
public class Parent
{
public static int t = parentStaticMethod2();
{
System.out.println("父类非静态初始化块");
}
static
{
System.out.println("父类静态初始化块");
}
public Parent()
{
System.out.println("父类的构造方法");
}
public static int parentStaticMethod()
{
System.out.println("父类类的静态方法");
return 10;
}
public static int parentStaticMethod2()
{
System.out.println("父类的静态方法2");
return 9;
}
@Override
protected void finalize() throws Throwable
{
// TODO Auto-generated method stub
super.finalize();
System.out.println("销毁父类");
}
}
public class Child extends Parent
{
{
System.out.println("子类非静态初始化块");
}
static
{
System.out.println("子类静态初始化块");
}
public Child()
{
System.out.println("子类的构造方法");
}
public static int childStaticMethod()
{
System.out.println("子类的静态方法");
return 1000;
}
@Override
protected void finalize() throws Throwable
{
// TODO Auto-generated method stub
super.finalize();
System.out.println("销毁子类");
}
}
public class Test
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
Parent.parentStaticMethod();
// Child child = new Child();
}
}
输出
父类的静态方法2 父类静态初始化块 父类类的静态方法
类中static 方法在第一次调用时加载,类中static成员按在类中出现的顺序加载。当调用静态方法2时输出
父类的静态方法2 父类静态初始化块 父类的静态方法2
注释掉Parent.parentStaticMethod();
去掉注释Child child = new Child();
父类的静态方法2 父类静态初始化块 子类静态初始化块 父类非静态初始化块 父类的构造方法 子类非静态初始化块 子类的构造方法
注意:构造器是在静态代码块和非静态代码块执行后再执行的
试着从原理上来分析:
1. 类的成员有method、field、innerClass等,分别又有静态和非静态两种
2. 静态成员是给类用的,非静态成员是给对象用的(对象如果使用静态成员编译会提示)
3. 类只要被用到,就会加载;必须先加载后使用
4. 使用类有两种,一种是只使用类的静态成员而不构造对象,这样的话就不需要初始化非静态的成员了;第二种是构造对象,构造对象必须先加载类,此时非静态成员在加载时也就初始化了,之后初始化非静态成员
5. 为什么先初始化静态成员,后初始化非静态成员
静态成员是一次性加载的,而且只加载一次;非静态成员可以使用静态成员,这样必须保证在非静态成员可能用到静态成员之前初始化完毕
6. 为什么先初始化父类,后初始化子类
子类可能用到父类的方法,必须保证子类使用之前是得父类可能用到的成员初始化完毕。
(1)使用子类静态成员时,不能使用子类自己的非静态成员,不能使用父类的非静态成员,只可能使用到父类的静态成员;这也解释了为什么加载子类(第一次使用子类)时,父类的非静态成员没有初始化
(2)使用子类的非静态成员时,可能用到子类自己的静态成员、父类的静态成员、父类的非静态成员
7. 为什么先初始化成员,后初始化构造函数
在构造函数中,可以对成员进行赋值,也可以不进行操作,但是可以使用非静态成员。因此必须保证构造函数可能用到的成员先初始化,否则就会报错。
8. 为什么父类构造方法执行要在子类非静态成员之前
子类非静态成员可能用到父类的非静态成员,而父类的非静态成员有可能是要在构造函数中才能正确初始化的,默认的初始化值可能不是理想的。构造函数的目的更多的是为了根据实际需求重新初始化成想要的值以待用。