先上一张我精心绘制的xmind总结图,想要原图的可以联系我:864057710
下面我们针对上面的一些知识点进行分析:
类加载机制主要分为三大步:加载——连接——初始化;其中连接又可以细分为验证、准备和解析。
这些步骤当中,主要涉及的知识点在初始化这一块。
什么时候初始化
下面我们结合一些代码的例子进行说明:
1、子类调用父类中的静态属性,不会触发子类的初始化
public class Father {
public static int abc = 1;
static {
System.out.println("Father is init");
}
}
public class Sun extends Father {
static {
System.out.println("Sun is init");
}
}
public class Test {
public static void main(String[] args) {
System.out.println(Sun.abc);
}
}
上面的代码输出是什么?你能回答对吗?换一个提问方法:这种情况下,子类是否会初始化?
根据输出,我们可以看到子类并没有初始化。
2、调用一个类中的静态方法时,会进行类的初始化
public class Father {
public static int abc = 1;
static {
System.out.println("Father is init");
}
public static void hello() {
System.out.println("hello");
}
}
public class Test1 {
public static void main(String[] args) {
Father father = null;
father.hello();
}
}
3、初始化情况-综合难题
下面这题,如果你能做对,并且想明白,那你对初始化这块基本就掌握了。
public class Test2 {
static int count = 0;
static {
count++;
System.out.println("A");
}
Test2() {
System.out.println("B");
}
}
class B {
static {
Test2 test2;
System.out.println("c");
}
public static void main(String[] args) {
Class c1;
Class c2;
Class c3;
try {
c1 = Test2.class;
c2 = Class.forName("com.ysy.类加载.Test2");
Test2 test2 = new Test2();
c3 = test2.getClass();
} catch (Exception e) {
e.printStackTrace();
return;
}
if (c2 == c1 && c1 == c3) {
System.out.println("D");
} else {
System.out.println("E");
}
System.out.println(Test2.count);
}
}
输出结果是:C A B D 1.
解析:Class中有main方法,首先被初始化,先执行它的静态赋值块,输出C;c1 = Test2.class;和c2 = Class.forName(“com.ysy.类加载.Test2”);只会加载Test2,调用静态代码块,不会调用器构造函数,接着count =1,输出A;Test2 test2 = new Test2();调用构造函数,输出B;因为类的加载信息只会在永久代里留存一份,所以c1,c2,c3实际上共用同一个ClassA.class对象,所以输出“D”。