让写作成为一种习惯,作文库欢迎您!
当前位置:首页 > > 考试 > > 计算机类 >

Java类和对象的初始化顺序

2021-04-25 15:40:01计算机类访问手机版559

Java类和对象的初始化顺序

  Java类和对象的初始化顺序

  在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化,其中链接又可以分成校验、准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的。下面一起来看看吧!

  类装载步骤

  在Java中,类装载器把一个类装入Java虚拟机中,要经过三个步骤来完成:装载、链接和初始化,其中链接又可以分成校验、准备和解析三步,除了解析外,其它步骤是严格按照顺序完成的,各个步骤的主要工作如下:

  装载:查找和导入类或接口的二进制数据;

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

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

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

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

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

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

  1.类的初始化initialization class & interface

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

  因为类的初始化其实是类加载loading of classes的最后一步,所以很多书中把它归结为“对象的创建”的第一步。其实只是看问题的角度不同而已。为了更清楚的理解,这里还是分开来。

  顺序:

  因为类的加载肯定是第一步的,所以类的初始化在前。大体的初始化顺序是:

  类初始化 -> 子类构造函数 -> 父类构造函数 -> 实例化成员变量 -> 继续执行子类构造函数的语句

  下面结合例子,具体解释一下。

  1. 类的初始化Initialization classes and interfaces

  其实很简单,具体来说有:

  a初始化类initialization of class,是指初始化static field 和执行static初始化块。

  public class Demo //初始化static field, //其中= "initialization static field"又叫做static field initializer private static String str = "initialization static field"; //初始化块,又叫做static initializer,或 static initialization block static System.out.println"This is static initializer";

  btw,有些书上提到static initializer 和 static field initializer 的概念,与之对应的还有 instance initializer 和 instance variable initializer。例子中的`注释已经解释了其含义。

  b初始化接口initialization of interface,是指初始化定义在该interface中的field。

  *注意*

  1. initialization classes 时,该class的superclass 将首先被初始化,但其实现的interface则不会。

  initialization classes 时,该class的superclass,以及superlcass的superclass 会首先被递归地初始化,一直到java.lang.Object为止。但initialiazation interface的时候,却不需如此,只会初始化该interface本身。

  2. 对于由引用类变量class field所引发的初始化,只会初始化真正定义该field的class。

  3. 如果一个static field是编译时常量compile-time constant,则对它的引用不会引起定义它的类的初始化。

  为了帮助理解最后两点,请试试看下面的例子:

  Initialization类

  public class Initialization static System.out.println"Initialization Main class"; public static void mainString[] args System.out.printlnSub.y; System.out.printlnSub.x; System.out.printlnSub.z;

  Sub类

  public class Sub extends Super public static final int y = 2005; public static int z; static System.out.println"Initialization Sub";

  Super类

  public class Super public static int x = 2006; static System.out.println"Initialization Super";

  输入结果

  Initialization Main class

  2005

  Initialization Super

  2006

  Initialization Sub

  从这个结果可以看到,

  static块在类中会先执行;实际上是先加载static成员变量,然后是static代码块

  static 的final变量不会引起类的初始化;

  子类Sub引用父类Super里面的变量,就会引起父类的初始化,但不会引起子类的初始化;

  static的成员变量也有默认值。

  2. 对象的创建creation of new class instances

  看例子来说明:

  InitializationOrder类

  public class InitializationOrder public static void mainString[] args SubClass sb = new SubClass;

  SuperClass类

  public class SuperClass static System.out.println"SuperClass static"; SuperClassString str System.out.printlnstr;

  Interface类

  interface Interface static SuperClass su = new SuperClass"Interface new SuperClass";

  SubClass类

  public class SubClass extends SuperClass implements Interface static System.out.println"SubClass static"; private SuperClass su = new SuperClass"initialization variable"; SubClass super"super"; new SuperClass"new SuperClass";

  输出结果

  SuperClass static

  SubClass static

  super

  initialization variable

  new SuperClass

  解释一下:

  1 Java虚拟机要执行InitializationOrder类中的static 方法main,这引起了类的初始化。开始初始化InitializationOrder类。具体的步骤略去不说。

  2 InitializationOrder类初始化完毕后,开始执行main方法。语句SubClass sb = new SubClass将创建一个SubClass对象。加载类SubClass后对其进行类初始化,因为Subclass有一个父类SuperClass,所以先初始化SuperClass类。于是看到输出“SuperClass static”。

  3 SuperClass类初始化完毕后,开始初始化SubClass类,输出“SubClass static”。

  4 至此,类的加载工作全部完成。开始进入创建SubClass的对象过程。先为SubClass类和其父类SuperClass类分配内存空间,这时Super su 被赋值为null。

  5 执行构造函数SubClass,执行super, 调用父类的构造函数,输出“super”。

  6 初始化SubClass类的成员变量su,输出“initialization variable”。

  7 继续执行构造函数的剩余部分,执行new SuperClass"new SuperClass",输出“new SuperClass”,这时Super su 被赋值新建对象的引用。

  8 而SubClass虽然实现了接口Interface,但是初始化它的时候并不会引起接口的初始化,所以接口Interface中的static SuperClass su = new SuperClass"Interface new SuperClass"自始至终都没有被执行到。

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

  1 所有的成员变量—包括该类,及它的父类中的成员变量--被分配内存空间,并赋予默认值。这里是第一次初始化成员变量

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

  3 如果在构造函数中用this 调用了同类中的其他构造函数,则按照步骤2~6去处理被调用到的构造函数。

  4 如果在构造函数中用super调用了其父类的构造函数,则按照步骤2~6去处理被调用到的父类构造函数。

  5 按照书写顺序,执行instance initializer 和 instance variable initializer来初始化成员变量。这里是第二次初始化成员变量

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

  总结:

  从类的初始化和对象的创建步骤,可以知道,一个类是先初始化static的变量和static句块,然后在分配该类以及父类的成员变量的内存空间,赋予默认值,然后开始调用构造函数。而子类和父类之间,则先初始化和创建父类,然后在初始化和创建子类的。