第一题
public class Test3 {
public static Test3 t = new Test3();
{
System. out .println("blockA" );
}
public Test3() {
}
static{
System. out .println("blockB" );
}
public static void main(String[] args) {
Test3 t1 = new Test3();
}
}
答案:
blockA
blockB
blockA
解析:
- JVM调用mian方法,发现Test类还没有被加载
- 加载Test类,类加载的准备阶段,会给类变量赋默认值,所以t1的默认值为null
- 类加载的最后一个阶段是初始化,先执行new Test();
- 实例化一个Test对象,先执行构造代码块,再执行构造函数,所以先输出“blockA”
- 然后执行静态代码块,输出“blockB”
- 当Test被加载完成后,执行main方法中的new Test();和第四步类似,先执行构造代码块,再执行构造函数,所以输出“blockA”
第二题
class SingleTon {
private static SingleTon singleTon = new SingleTon();
public static int count1;
public static int count2 = 0;
private SingleTon() {
count1++;
count2++;
}
public static SingleTon getInstance() {
return singleTon;
}
}
public class Test {
public static void main(String[] args) {
SingleTon singleTon = SingleTon.getInstance();
System.out.println("count1=" + singleTon.count1);
System.out.println("count2=" + singleTon.count2);
}
}
答案:
count1=1
count2=0
解析:
- main方法引发SingleTon类的加载
- 在类加载准备阶段给静态变量赋默认值,singleTon=null,count1=0,count2=0
- 然后执行初始化操作(给静态变量赋值+执行静态代码块),执行new SingleTon();先执行构造函数,此时count1=1,count2=1
- 继续赋值count1,count2。因为count1没有赋值操作,估count1不变,count2为0
第三题
public class Parent {
int a = 10;
static int b = 11;
// 静态代码块
static {
System.out.println("Parent静态代码块:b=" + b);
b++;
}
// 代码块
{
System.out.println("Parent代码块: a=" + a);
System.out.println("Parent代码块: b=" + b);
b++;
a++;
}
// 无参构造函数
Parent() {
System.out.println("Parent无参构造函数: a=" + a);
System.out.println("Parent无参构造函数: b=" + b);
}
// 有参构造函数
Parent(int a) {
System.out.println("Parent有参构造函数: a=" + a);
System.out.println("Parent有参构造函数: b=" + b);
}
// 方法
void function() {
System.out.println("Parent function run ……");
}
}
public class Child extends Parent {
int x = 10;
static int y = 11;
// 静态代码块
static {
System.out.println("Child静态代码块:y=" + y);
y++;
}
// 代码块
{
System.out.println("Child代码块: x=" + x);
System.out.println("Child代码块: y=" + y);
y++;
x++;
}
// 构造函数
Child() {
System.out.println("Child构造函数: x=" + x);
System.out.println("Child构造函数: y=" + y);
}
// 方法
void function() {
System.out.println("Child function run ……");
}
}
public class Test {
public static void main(String[] args) {
Child demo = new Child();
demo.function();
System.out.println("…………………………………………………………………………………………………………………………");
Child child = new Child();
child.function();
}
}
答案:
Parent静态代码块:b=11
Child静态代码块:y=11
Parent代码块: a=10
Parent代码块: b=12
Parent无参构造函数: a=11
Parent无参构造函数: b=13
Child代码块: x=10
Child代码块: y=12
Child构造函数: x=11
Child构造函数: y=13
Child function run ……
--------------------------------
Parent代码块: a=10
Parent代码块: b=13
Parent无参构造函数: a=11
Parent无参构造函数: b=14
Child代码块: x=10
Child代码块: y=13
Child构造函数: x=11
Child构造函数: y=14
Child function run ……
解析:
1.执行new Child()触发父类Parent的加载
2.Parent类加载的准备阶段为类变量(静态变量)分配内存,赋默认值b=0
3.Parent类加载的最后一个阶段,初始化类变量(静态变量),执行静态代码块
4.b=11,输出‘Parent静态代码块:b=11’,执行完毕后b=12
5.然后加载Child类
6.Child加载准备阶段,未类变量赋默认值y=0
7.Child加载最后阶段,初始化类变量执行静态代码块
8.y=11,输出‘Child静态代码块:y=11’,执行完毕后y=12
9.然后实例化Child对象
10.先执行父类Parent的构造函数
10.1-初始化非类变量a=10
10.2-执行构造代码块
10.3-执行构造函数
11.执行Child的构造函数
11.1-初始化非类变量x=10
11.2-执行构造代码块
11.3-执行构造函数
12.执行Child对象demo.function方法
13.再次实例化Child,其父类Parent已经加载过了。Child也加载过了。
14.先执行父类构造方法
14.1-初始化非类变量a=10
14.2-执行构造代码块
14.3-执行构造函数
15.执行Child构造函数
15.1-初始化非类变量x=10
15.2-执行构造代码块
15.3-执行构造函数
16.执行Child对象child.function方法