java面试类的初始化

首先要知道如下几个知识点:

  • 初始化类有如下几个步骤:
    • 加载 (将一个class从硬盘读取到内存中)
    • 连接
      • 验证 (验证class类的合法性)
      • 准备 (为类的静态变量分配内存,并将其初始化为默认值)
      • 解析 (将类中的符号引用转换为直接引用)
    • 初始化 (为类的静态变量赋予正确的初始值)
  • 只有当对类进行主动使用的时候才会初始化该类
  • 类的主动使用有如下6种:
    • 实例化该类
    • 调用该类的静态方法
    • 访问该类或接口的静态属性或为该类或接口的静态属性赋值 (接口也可以初始化)
    • class.forname()的方式
    • 初始化一个类的子类也叫做对其父类的主动使用
    • Java虚拟机启动的时候被标明为启动类的类即包含main方法的类 例如:java Test

下面代码输出结果是什么?

class Sample {

    public static Sample sample = new Sample();
    public static int c;
    public static int c2 = 0;
    
    private Sample() {
        c++;
        c2++;
    }
    
    public static Sample getInstance() {
        return sample;
    }
}

public class Inherit {

    public static void main(String[] args) {
        Sample sample = Sample.getInstance();
        System.out.println(sample.c);
        System.out.println(sample.c2);
    }
}

输出结果是1、0为什么呢?

首先启动类是Inherit类,所以是对该类的主动使用即会先初始化该类,然后执行main方法,Sample.getInstance()是调用了Sample类的静态方法,因此会初始化Sample类,在连接的准备阶段会为属性sample、c、c2分别设置默认值null、0、0.当执行到初始化阶段则会为它们赋予正确的属性值即先执行sample = new Sample();当执行完该语句后c、c2的值都变为了1、1,然后执行接下来的语句。因为变量c没有显式的赋予值所以跳过,c2显式的赋了值所以c2由1转变为了0

下面代码的输出结果是什么?

public class Parent {

    public static String s = "a";
    
    static  {
        System.out.println("Parent static block");
    }
    
    public Parent() {
        System.out.println("Parent constructor");
    }
}

public class Child extends Parent {
    
    static String str = "child";
    
    static {
        System.out.println("child static");
    }
    
    public Child() {
        System.out.println("child constructor");
    }

}

public class InheritTest {

    public static void main(String[] args) {
        new Child();
    }
}

输出结果是:

Parent static block
child static block
Parent constructor
child constructor

先初始化了父类,再初始化子类,接着执行父类的构造方法,最后再执行子类的构造方法。记住一句话即静态先行

你可能感兴趣的:(java面试类的初始化)