1.类的加载顺序
package com.example.demo.test;
public class MyTest5 {
public static void main(String[] args){
Singleton singleton=new Singleton();
}
}
class Singleton{
{
System.out.println("这是代码块");
}
static {
System.out.println("这是静态代码块");
}
public Singleton(){
System.out.println("构造方法");
}
}
执行结果是
这是静态代码块
这是代码块
构造方法
总结:初始化对象的时候static修饰的变量或者方法都会被首先执行,然后再去做普通的初始化,再去进行实例化;
1.关于类加载器
通过执行以下代码获取类的加载器
package com.example.demo.test;
public class MyTest6 {
public static void main(String[] args) throws Exception{
Class<?> clazz=Class.forName("com.example.demo.test.C");
System.out.println(clazz.getClassLoader());
}
}
class C{
}
执行结果是
总结:如果去判断String类型的加载器,它的返回结果是null,因为它是根类加载器去加载的。而加载C的加载器是AppClassLoader
查看AppClassLoader所在的位置为rt.jar包下的Launcher.class中的AppClassLoader.class
package com.example.demo.test;
public class MyTest7 {
static{
System.out.println("this is MyTest7");
}
public static void main(String[] args) {
System.out.println(Child.x);
}
}
class Parent{
public static int x=3;
static{
System.out.println("this is static Parent");
}
}
class Child extends Parent{
static int b =4;
static {
System.out.println("this is static Child");
}
}
得出结果
总结:如果通过子类的对象调用父类的属性,则这是对父类的主动使用,而不是对子类的主动使用,所以子类不会被初始化。
观察类什么时候被加载
package com.example.demo.test;
public class MyTest8 {
public static void main(String[] args) throws Exception{
ClassLoader loader=ClassLoader.getSystemClassLoader();
Class<?> clazz=loader.loadClass("com.example.demo.test.CL");
System.out.println(clazz);
System.out.println("-----------------------");
clazz=Class.forName("com.example.demo.test.CL");
System.out.println(clazz);
}
}
class CL{
static {
System.out.println("this is CL");
}
}
通过执行以上代码,可以得出结果
总结:通过类加载器去加载类不会导致类的初始化,而只有通过反射才会去初始化类,因为只有反射才符合类的主动使用的特性。