1.请先看Demo:
class Initable1Parent { static { System.out.println("Initializing Initable1Parent..."); } } class Initable2Parent { static { System.out.println("Initializing Initable2Parent..."); } } class Initable1 extends Initable1Parent{ static { System.out.println("Initializing Initable1..."); } } class Initable2 extends Initable2Parent{ static { System.out.println("Initializing Initable2..."); } } public class InitializeDemo { @Test public void test01() throws Exception { //使用.class方式加载字节码 Class initable1Clazz = Initable1.class; //使用Class.forName(String className)方式加载字节码 Class initable2Clazz = Class.forName("com.tca.thinkInJava.chap14.test.Initable2"); } }
执行结果:
Initializing Initable2Parent... Initializing Initable2...
可以看出:
使用.class方式加载类并没有对该类及其父类进行静态初始化(并没有执行Initable1Parent和Initable1的静态代码块),但是使用Class.forName(String className)方式则对该类和父类进行了静态初始化。
2. 再看Demo
class Mouse { public static final String type = "Mouse"; static { System.out.println("Initializing Mouse..."); } } class Cat { public static String type = "Cat"; static { System.out.println("Initializing Cat..."); } } public class InitializeDemo { @Test public void test02() { Class dogClazz = Mouse.class; System.out.println(Mouse.type); Class catClazz = Cat.class; System.out.println(Cat.type); } }
执行结果:
Mouse Initializing Cat... Cat
可以看出:
1. 使用.class方式加载字节码时,并没有对类进行静态初始化(因为没有执行static静态代码块,但是已经由类加载器进行了加载,且对静态成员变量分配了存储空间)
2. 对于静态成员变量,使用final修饰与未使用final修饰(静态常量与静态非常量)之间的区别:
如果类中使用static和final修饰了,则该类在没有初始化时,也可以直接访问其静态常量。如Demo中的Mouse,并没有执行Mouse类的静态代码块,但依然可以访问静态常量type,但是没有final则不同,同样没有使用.class方式进行类加载时,即没有对类进行初始化时,我们直接访问Cat类的静态成员变量(非final修饰),会先对该Cat类进行初始化,才可以访问其静态成员变量type