美文网首页
一道面试题到java类加载过程的思考

一道面试题到java类加载过程的思考

作者: gigglesoso | 来源:发表于2020-05-13 21:57 被阅读0次

    运行下面代码执行过程是怎么样的?

    public class Test {
        public static void main(String[] args) {
            System.out.println(T.count);
        }
    }
    class T{
        public static int count = 2;
        public static T t= new T();
        private T(){
            count++;
        }
    }
    

    假如调换T中count变量和t变量的顺序呢?

    public class Test {
        public static void main(String[] args) {
            System.out.println(T.count);
        }
    }
    class T{
        public static T t = new T();
        public static int count = 2;
        private T(){
            count++;
        }
    }
    

    ————————————————————————————————

    要搞清楚这两个问题,我们需要知道当我们调用T.count的时候到底发生了什么?

    调用T.count时候,其实一个总的过程是加载了T这个的类对象,因为java中类加载使用lazyloading,真正在调用时候才会发生。所以上述过程其实是加载T的类对象,再输出他的变量值的问题。
    ————————————————————————————————

    类加载的过程包含以下三个阶段
    • Loading(加载阶段)
      这是一个将.class文件加载进内存的过程,双亲委派就是发生在这个阶段
    • Linking(连接阶段)
      这个阶段又分为三个小阶段:
      --Verification(校验阶段)主要是校验loading进的class文件是否符合class文件的标准
      --Preparation(准备阶段)把class文件的静态变量赋初始值,一般int初始值就是0,引用类型的初始值就是null
      --Resolution(解析阶段)把class文件常量池里面的符号引用转换为直接内存地址
    • Initializing(初始化阶段)
      这个阶段给静态变量赋值
      ————————————————————————————————
      知道了这个过程我们来分析上面的例子。
    • 第一种情况:
      在Preparation阶段,先给变量赋初始值,int count = 0,T t = null;
      在Initializing阶段给变量赋值,int count = 2,T t = new T();
      由于调用new T()时候会调用它的无参构造方法,执行了count++,此时count = 3。
      因此这种情况输出值为3。
    • 第二种情况:
      在Preparation阶段,先给变量赋初始值,T t = null,int count = 0;
      在Initializing阶段给变量赋值,先执行new T()调用了无参构造,此时执行了count++,所以执行完new T(),count变为了1,然后1会被赋值的时候被2给覆盖掉,所以这种情况count = 2。
      因此这种情况输出值为2。

    相关文章

      网友评论

          本文标题:一道面试题到java类加载过程的思考

          本文链接:https://www.haomeiwen.com/subject/ihxqnctx.html