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