类初始化的一道面试题

下面的代码counter1,counter2输出的结果是什么,把第10行放到12行后面,ounter1,counter2输出的结果是什么? 为什么?

 1 public class Test {
 2     public static void main(String[] args) {
 3         System.out.println(Singleton.counter1);
 4         System.out.println(Singleton.counter2);
 5     }
 6     
 7 }
 8 
 9 class Singleton{
10     private static Singleton singleton = new Singleton();
11     public static int counter1;
12     public static int counter2=0;
13     private Singleton(){
14         counter1++;
15         counter2++;
16     }
17     public static Singleton getInstance(){
18         return singleton;
19     }
20 }

1. counter1=1,counter2=0

  原因是类初始化的准备阶段,会为静态变量分配内存,并设置默认初始值,此时singleton=null,counter1=0,counter2=0;然后在初始化阶段,为静态变量赋初始值,这时从上往下初始化,先new Singleton(), counter1=1,counter2=1,然后11行counter1没变,counter2被重新赋值为0。

2. counter1=1,counter2=1

  原因是代码顺序换了,new Singleton()在后面执行。

 

类的初始化时机:主动使用(六种)

– 创建类的实例

– 访问某个类或接口的静态变量,或者对该静态 变量赋值

– 调用类的静态方法

– 反射(如 Class.forName(“com.shengsiyuan.Test”) )

– 初始化一个类的子类 – Java虚拟机启动时被标明为启动类的类(Java Test) 

除了上述六种情形,其他使用Java类的方 式都被看作是被动使用,不会导致类的初始化 

其他情况一:只有当程序访问的静态变量或静态方法确 实在当前类或当前接口中定义时,才可以 认为是对类或接口的主动使用 

 1 public class Test {
 2     public static void main(String[] args) {
 3         System.out.println(Child.a);
 4     }
 5 }
 6 
 7 class Parent {
 8     static int a = 3;
 9     static {
10         System.out.println("Parent static block");
11     }
12     static void doSomething(){
13         System.out.println("do something");
14     }
15 }
16 class Child extends Parent{
17     static {
18         System.out.println("Child static block");
19     }
20 }

输出

Parent static block
3

子类的静态代码块没有被执行,说明子类没有被初始化。

其他情况二:调用ClassLoader类的loadClass方法加载 一个类,并不是对类的主动使用,不会导 致类的初始化。 

 1 public class Test {
 2     public static void main(String[] args) throws ClassNotFoundException {
 3         ClassLoader loader = ClassLoader.getSystemClassLoader();
 4         Class<?> clazz = loader.loadClass("com.test.CL");
 5         System.out.println("---------------");
 6         clazz = Class.forName("com.test.CL");
 7     }
 8 }
 9 
10 class CL {
11     static {
12         System.out.println("Class CL");
13     }
14 }

输出

---------------
Class CL

ClassLoader的loadClass不会对类进行初始化。

posted @ 2018-04-23 12:23  Mr.years  阅读(201)  评论(0编辑  收藏  举报