Java类的装载

  在Java中,类装载器把java类装载到虚拟机中,经过装载,链接和初始化三个步骤来完成。

其中链接中包括 校验、准备和解析。

下面对这些概念进行解析:

装载:查找和导入类或接口的二进制数据,常用的是根据类的路径加载,还有根据网络的地址加载。

链接:执行校验、准备和解析步骤,其中解析步骤是可以选择的;

      校验:检查导入类或接口的二进制数据的正确性;

      准备:给类的静态变量分配并初始化存储空间;

      解析:将符号引用转成直接引用;

初始化:激活类的静态变量的初始化Java代码和静态Java代码块。

其中 初始化(initialization)包含两部分:

1.类的初始化(initialization class & interface)---初始化静态变量和静态Java代码块

2.对象的创建(creation of new class instances)----new class()。

用一个简单的流程分析如下:

普通对象初始化                                                        继承体系对象初始化            

       

java 初始化实现了interface对象 java初始化类的对象_父类

  

java 初始化实现了interface对象 java初始化类的对象_java_02

 

           

初始化

1.类的初始化,也就是静态变量以及静态块的初始化

    1.1 如果有继承父类有静态变量或者静态块的,先执行初始化。

    1.2 如果是final static ,那么就不会初始化类

    1.3 如果执行的是父类的静态变量,那么子类不会初始化

public class SuperTmp { 
  
   

                 public static int a = 10;    
  
   

                 public final static int b = 20;    
  
   

                 public int c = 10; 
  
   

                 static{ 
  
   

                        System.out.println("init super calss..."); 
  
   

                  }    
  
   

               public SuperTmp (){ 
  
   

                        System.out.println("super init constructor:"); 
  
   

                 }  
  
   

           } 
  
   

         public class Sub extends SuperTmp { 
  
   

                 public static  final int aa = 30; 
  
   

                 public static int bb = 40; 
  
   

                 public int cc = 20; 
  
   

                 static { 
  
   

                        System.out.println("init sub class....."); 
  
   

                 } 
  
   

                public Sub (){ 
   
    

       
   
    

                         System.out.println("sub init constructor:" ); 
   
    

                  }  
   
   

          } 
  
   

        public class Play { 
  
   

                  public static void main(String[] args) {     
  
   

                   /**输出 
  
   

                     * init super calss... 
  
   

                     * 10 
  
   

                     * 不会初始化子类 Sub 
  
   

                     */ 
  
   

                      System.out.println(Sub.a);    
  
   

                    /****** 
  
   

                      *  输出 b 不会初始化任何类 
  
   

                      */ 
  
   

                      System.out.println(Sub.b); 
  
   

                    /*** 
  
   

                      * 输出 
  
   

                      * init super calss... 
  
   

                      *  init sub class..... 
  
   

                      *  40 
  
   

                      */ 
  
   

                    System.out.println(Sub.bb); 
  
   

                   /*对象初始化 
  
   

                     *init super calss... 
  
   

                       init sub class..... 
  
   

                     *super init constructor 
  
   

                      sub init constructor 
  
   

                     */ 
  
   

                   Sub sb = new Sub() 
  
   

                  } 
  
   

                }

2.创建class的对象

    2.1.先为Sub类和其父类SuperTmp类分配内存空间,父类和子类的变量都初始化值,对象类型的为null,

       基本数据类型的为默认的值,例如 int 类型的为初始化 0

   2.2  执行构造函数Sub(), 调用父类的构造函数,输出“super init constructor”,“sub init constructor”。

   2.3  初始化superTmp,Sub类的成员变量,并赋值

   2.4  对于类实现了接口Interface,初始化它的时候并不会引起接口的初始化。

 

所以对象的创建,具体步骤如下:

(1) 所有的成员变量—包括该类,及它的父类中的成员变量--被分配内存空间,

   并赋予默认值。(第一次初始化成员变量)

(2) 为所调用的构造函数初始化其参数变量。(如果有参数)

(3) 如果在构造函数中用this 调用了同类中的其他构造函数,

   则按照步骤(2)~(6)去处理被调用到的构造函数。

(4) 如果在构造函数中用super调用了其父类的构造函数,

   则按照步骤(2)~(6)去处理被调用到的父类构造函数。

(5) 按照书写顺序,执行instance initializer 和 instance variable initializer

   来初始化成员变量。(第二次初始化成员变量)

(6) 按照书写顺序,执行构造函数的其余部分。

总结:

  从类的初始化和对象的创建步骤,可以知道,一个类是先初始化static的变量和static句块,

  然后在分配该类以及父类的成员变量的内存空间,赋予默认值,然后开始调用构造函数。

  而子类和父类之间,则先初始化和创建父类,然后再初始化和创建子类的。