运行下面代码执行过程是怎么样的?
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。
网友评论