首先要知道如下几个知识点:
- 初始化类有如下几个步骤:
- 加载 (将一个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
先初始化了父类,再初始化子类,接着执行父类的构造方法,最后再执行子类的构造方法。记住一句话即静态先行
网友评论