类初始化与实例初始化

  咱们的类初始化在类被加载时就会执行,这里类被加载并不必定要实例化类的对象,只要jvm在第一次用到这个类的方法或者属性时发现内存中没有加载过这个类,就会对类进行初始化。jvm

  当类初始化时被加载到内存中的方法区中,并次建立成一个class对象存储类的信息,而后分配内存执行,类中的静态属性的显式赋值语句和静态代码块被放在一个叫<clinit>的方法中执行(按属性和静态代码块在代码中书写的spa

顺序加载),这里要注意,对于每个类,<clinit>方法只在类第一次被调用时执行一次,当第二次调用这个类的方法或者属性时,就不会再被执行。code

  当被使用的类是某个类的子类时,这时首先初始化父类,而后再初始化子类,一样的,父类也只被能被初始化一次,以后使用不会再被初始化,对于一个类,<clinit>方法只执行一次 对象

  而实例初始化是在实例化类的对象时进行的,也就是说,只要实例化一个对象,就会进行一次实例初始化。 blog

  实例初始化过程和类初始化过程类似,但都是非静态的,非静态属性的显式赋值和构造代码块还有构造器(注意注意:构造器是最后被初始化,其余的属性和代码块按代码书写的顺序加载)一块儿被放在一个叫<init>的方法中执行,每建立一继承

个对象就初始化一次,这一点和类初始化不一样。内存

 

  下面提供几个例题帮助理解:get

  第一题比较综合,可从第二题开始it

 1 public class Test1 {  2     public static void main(String[] args) {  3         Zi zi = new Zi();//1 首先进入主方法,看到类被实例化,先进行类的初始化,而后进行实例初始化
 4  }  5 }  6 class Fu{  7     private static int i = getNum("(1)i");//3 首先进行静态属性的加载, 执行getNum方法
 8     private int j = getNum("(2)j");//11 实例初始化父类,加载非静态属性
 9     static{ 10         print("(3)父类静态代码块");//6 加载静态代码块并打印 (3)父类静态代码块->1,父类实例化完毕
11  } 12  { 13         print("(4)父类非静态代码块,又称为构造代码块");//14 加载构造代码块 打印(4)父类非静态代码块,又称为构造代码块->2
14  } 15  Fu(){ 16         print("(5)父类构造器");//15最后调用构造器,打印 (5)父类构造器->2 父类实例初始化完成 ,进入子类
17  } 18     public static void print(String str){//5 打印(1)i->0 //13 (2)j->1
19         System.out.println(str + "->" + i); 20  } 21     public static int getNum(String str){//4 //12
22  print(str); 23         return ++i; 24  } 25 } 26 class Zi extends Fu{//2 找到对象所在类发现存在继承关系,因此转到父类先进行父类的初始化
27     private static int k = getNum("(6)k");//7 进入子类实例化,方法同
28     private int h = getNum("(7)h");//16同父类
29     static{ 30         print("(8)子类静态代码块");//10 (8)子类静态代码块->1 子类初始化完毕,开始进行实例初始化
31  } 32  { 33         print("(9)子类非静态代码块,又称为构造代码块");//19 (9)子类非静态代码块,又称为构造代码块->2
34  } 35  Zi(){ 36         print("(10)子类构造器");//20 (10)子类构造器->2
37  } 38     public static void print(String str){//9 (6)k->0 //18 (7)h->1
39         System.out.println(str + "->" + k); 40  } 41     public static int getNum(String str){//8 //17
42  print(str); 43         return ++k; 44  } 45 }

执行结果:class

(1)i->03)父类静态代码块->16)k->08)子类静态代码块->12)j->14)父类非静态代码块,又称为构造代码块->25)父类构造器->27)h->19)子类非静态代码块,又称为构造代码块->210)子类构造器->2

 

 1 public class Test07 {  2     public static void main(String[] args) {  3         Son son = new Son();  4  }  5 }  6 class Father{  7     static{  8         System.out.println("(1)父类的静态代码块");  9  } 10  { 11         System.out.println("(2)父类的非静态代码块"); 12  } 13  Father(){ 14         System.out.println("(3)父类的无参构造"); 15  } 16 } 17 class Son extends Father{ 18     static{ 19         System.out.println("(4)子类的静态代码块"); 20  } 21  { 22         System.out.println("(5)子类的非静态代码块"); 23  } 24  Son(){ 25         System.out.println("(6)子类的无参构造"); 26  } 27 }

 执行结果:

(1)父类的静态代码块 (4)子类的静态代码块 (2)父类的非静态代码块 (3)父类的无参构造 (5)子类的非静态代码块 (6)子类的无参构造

 

 1     public static void main(String[] args) {  2         Sub s = new Sub();  3  }  4 }  5 class Base{  6  Base(){  7         method(100);  8  }  9  { 10         System.out.println("base"); 11  } 12     public void method(int i){ 13         System.out.println("base : " + i); 14  } 15 } 16 class Sub extends Base{ 17  Sub(){ 18         super(); 19         super.method(70); 20  } 21  { 22         System.out.println("sub"); 23  } 24     public void method(int j){ 25         System.out.println("sub : " + j); 26     }

执行结果:

base sub : 100 sub base : 70

这题要注意,执行父类构造时发现一个method方法,这时要看实例化的对象是什么,是子类就要看子类中有没有同名方法,不能盲目调用父类的方法

相关文章
相关标签/搜索