zoukankan      html  css  js  c++  java
  • Java初始化顺序

    成员变量的初始化顺序

    • 实例变量在声明处初始化
    • 实例变量在实例初始化块中初始化
    • 实例变量在构造器中初始化
    • 静态变量在声明处初始化
    • 静态变量在静态初始块中初始化

    将5种初始化代码无规则的分布在程序中,观察执行的顺序

     1 public class InitOrderTest {
     2 
     3     public InitOrderTest(int x, int y) {
     4         System.out.println("执行构造器···");
     5         this.x = x;
     6         this.y = y;
     7     }
     8 
     9     {
    10         System.out.println("执行实例初始化块1···");
    11     }
    12     private int x;
    13     private int y = initY();
    14 
    15     {
    16         System.out.println("执行实例初始化块2···");
    17         x = initX();
    18     }
    19 
    20     static {
    21         System.out.println("执行静态初始化块···");
    22     }
    23 
    24     private static int staticX;
    25     private static int staticY = initStaticY();
    26 
    27     static {
    28         System.out.println("执行静态初始化块2···");
    29         staticX = initStaticX();
    30     }
    31 
    32     public int initX() {
    33         System.out.println("执行实例变量x初始化···");
    34         return 1;
    35     }
    36 
    37     public int initY() {
    38         System.out.println("执行实例变量y初始化···");
    39         return 1;
    40     }
    41 
    42     public static int initStaticX() {
    43         System.out.println("执行静态变量staticX初始化···");
    44         return 1;
    45     }
    46 
    47     public static int initStaticY() {
    48         System.out.println("执行静态变量staticY初始化···");
    49         return 1;
    50     }
    51 
    52     public void show() {
    53         System.out.printf("x=%d,y=%d,staticX=%d,staticY=%d
    ", x, y, staticX,
    54                 staticY);
    55     }
    56 
    57     public static void main(String[] args) {
    58 
    59         System.out.println("执行main方法···");
    60         InitOrderTest iot1 = new InitOrderTest(10, 15);
    61         InitOrderTest iot2 = new InitOrderTest(20, 25);
    62         iot1.show();
    63         iot2.show();
    64 
    65     }
    66 
    67 }

    运行结果:

    分析结果:

    1. 当运行InitOrderTest类时,Java虚拟机试图调用该类的main方法时,JVM发现该类尚未加载,因此会首先加载该类,并会执行链接,在链接阶段会为该类的静态方法分配空间,并置为默认值,然后按照初始化在类中的顺序执行静态初始化(只执行一次)。

    2. 静态成员的初始化执行完成后,就会执行main方法,创建InitOrderTest类的对象,使用new在堆中为对象分配空间,这时所有的实例变量都设置为默认值。然后执行实例初始化。3种实例初始化方式,首先会按照实例变量在类中声明的初始化顺序执行(这里的顺序指的是初始化在类中声明的顺序,而不是变量在类中声明的顺序),然后执行构造器。

    3. 再次创建InitOrderTest类的对象时,不再执行静态初始化。但是每次创建一个对象都要执行一次实例变量初始化。

    继承下的初始化

     1 public class SubInitOrderTest extends InitOrderTest {
     2 
     3     private int z = initZ();
     4     private static int staticZ = initStaticZ();
     5 
     6     public SubInitOrderTest(int x, int y, int z) {
     7         super(x, y);
     8         System.out.println("执行子类构造器···");
     9         this.z = z;
    10     }
    11 
    12     public int initZ() {
    13         System.out.println("执行子类实例变量z初始化···");
    14         return 1;
    15     }
    16 
    17     public static int initStaticZ() {
    18         System.out.println("执行子类静态变量staticZ初始化···");
    19         return 1;
    20     }
    21 
    22     public static void main(String[] args) {
    23 
    24         new SubInitOrderTest(1, 2, 3);
    25     }
    26 
    27 }

    运行结果:

    分析执行过程:

    1. JVM调用子类的main首先加载、链接并尝试初始化子类,而子类继承了父类,所以在初始化子类之前,需要加载、链接并初始化父类,这是一个递归的过程,直到Object类。所以会首先执行父类中静态变量staticX与staticY和静态初始化块。

    2. 当父类与子类静态初始化完成后,执行子类的main方法,创建子类的对象。当子类对象创建时,就会执行实例初始化,而子类继承了父类,因此,首先会执行父类的实例初始化,这也是一个递归的过程,直到object类为止。因而父类的实例初始化会在子类的实例初始化之前完成。即首先执行父类中的实例变量x与y,还有两个实例初始化块与构造器,然后执行子类中实例变量z、实例初始化块与构造器。

    总结:

    • 初始化的顺序可以简单的总结为先静态,后实例,先父类,后子类。对于静态初始化,按照静态变量声明处初始化与静态初始化块在类中出现的顺序执行。对于实例初始化,按照实例变量声明处初始化与实例初始化块在类中出现的顺序执行,然后执行构造器。
    • 当心潜在的向前引用,如果使用一个尚未初始化值的变量值,就可能得到错误的结果
    • 在构造器中不要调用可由子类重写的方法,调用private与final的方法才是安全的。
    • 对于值为编译时常量的final变量,可以认为这样的变量会最先得到初始化。在程序中无法观察到其默认值,即使向前引用这种类型的变量也是如此。
  • 相关阅读:
    动态规划----背包问题
    动态规划----最长公共子序列
    贪心算法---codeforce680D Bear and Tower of Cubes
    贪心算法----Fence Repair(POJ 3253)
    线段树拓展----HDU 6315 Naive Operations
    Saruman`s Army(POJ 3069)
    字典序最小问题 Best Cow Line (POJ 3617)
    RMQ
    牛客2018年第二次acm暑期培训----H-Diff-prime Pairs
    牛客2018年第二次多校培训----A-run
  • 原文地址:https://www.cnblogs.com/lahblogs/p/4357612.html
Copyright © 2011-2022 走看看