• Java类、实例初始化的顺序


    求如下 java 代码的输出??
    class T  implements Cloneable{
      public static int k = 0;
      public static T t1 = new T("t1");
      public static T t2 = new T("t2");
      public static int i = print("i");
      public static int n = 99;
      
      public int j = print("j");
      {
          print("构造快");
      }
      
      static {
          print("静态块");
      }
      
      public T(String str) {
          System.out.println((++k) + ":" + str + "    i=" + i + "  n=" + n);
          ++n; ++ i;
      }
      
      public static int print(String str){
          System.out.println((++k) +":" + str + "   i=" + i + "   n=" + n);
          ++n;
          return ++ i;
      }
      
      public static void main(String[] args){
          T t = new T("init");
      }
    }

    分析:  

    代码主要考察类、变量初始化的顺序

    一般的,我们很清楚类需要在被实例化之前初始化,而对象的初始化则是运行构造方法中的代码。

    代码组成:

    • 成员变量 2~6 行的变量是 static 的,为类 T 的静态成员变量,需要在类加载的过程中被执行初始化;第 8 行的int j则为实例成员变量,只再类被实例化的过程中初始化。

    • 代码段 9~11 行为实例化的代码段,在类被实例化的过程中执行;13~15 行为静态的代码段,在类被加载、初始化的过程中执行。

    • 方法 方法public static int print(String str) 为静态方法,其实现中牵涉到 k,i,n 三个静态成员变量,实际上,这个方法是专门用来标记执行顺序的方法;T 的构造方法是个实例化方法,在 T 被实例化时调用。

    • main 方法 main 方法中实例化了一个 T 的实例。

    执行顺序分析:

    在一个对象被使用之前,需要经历的过程有:类的装载 -> 链接(验证 -> 准备 -> 解析) -> 初始化 -> 对象实例化。(详情参见《Java 类的装载、链接和初始化》),这里需要注意的点主要有:

    • 在类链接之后,类初始化完成之前,实际上类已经可以被实例化了。

    就如此题代码中所述,在众多静态成员变量被初始化完成之前,已经有两个实例的初始化了。实际上,此时对类的实例化,除了无法正常使用类的静态成员变量以外(还没有保证完全被初始化),JVM 中已经加载了类的内存结构布局,只是没有执行初始化的过程。比如第 3 行public static T t1 = new T("t1");,在链接过程中,JVM 中已经存在了一个 t1,它的值为 null,还没有执行new T("t1")。又比如第 5 行的public static int i = print("i");,在没有执行初始化时,i 的值为 0,同理 n 在初始化前值也为 0.

    • 类实例化的过程中,先执行父类的构造器,然后执行隐式的构造代码,再执行构造方法中的代码

    实际上,在编译 Java 代码到字节码的过程中,编译器已经将源码中实例化相关的代码集中到了构造方法中。

    这里隐式的构造代码包括了{}代码块中的代码,以及实例成员变量声明中的初始化代码。它们的执行顺序以源代码中代码出现的顺序为准。为何不是先执行显示的构造方法中的代码,再执行隐式的代码呢?这也很容易解释:构造方法中可能就需要使用到实例成员变量,而这时候,我们是期待实例变量能正常使用的。

    有了如上的分析,也就能推到出最终的输出结果了。实际上,这几个原则都不需要死记硬背,完全能通过理解整个 JVM 的执行过程来梳理出思路的。

    答案:

    1:j   i=0   n=0
    2:构造快   i=1   n=1
    3:t1    i=2  n=2
    4:j   i=3   n=3
    5:构造快   i=4   n=4
    6:t2    i=5  n=5
    7:i   i=6   n=6
    8:静态块   i=7   n=99
    9:j   i=8   n=100
    10:构造快   i=9   n=101
    11:init    i=10  n=102

    转自:http://biaobiaoqi.github.io/blog/2013/09/22/java-initialization/

    新增:http://www.cnblogs.com/greatfish/p/5771548.html

  • 相关阅读:
    k8s 节点的 NodeAffinity 使用
    template 与 host , item trigger的关系
    mysql 性能优化思路
    nginx 配sorry page
    修改tomcat JVM 大小 jdk--目录修改
    (转)MySQL慢查询分析优化 + MySQL调优
    注册表操作 Microsoft.Win32.Registry与RegistryKey类
    C#(99):WCF之.NET Remoting通讯
    CallContext线程数据缓存-调用上下文
    C#(99):JSON与对象的序列化与反序列化
  • 原文地址:https://www.cnblogs.com/doubleqsweet/p/7055040.html
Copyright © 2020-2023  润新知