在java程序中每一个类都有一个Class对象,被保存在同名的.Class对象当中,JVM会使用类加载器加载Class文件生成类的对象信息.
当我们创建一个类的对象或者调用这个对象的静态方法,jvm会自动加载类的对象信息
获得类的对象信息
我们一般常用用两种方式获得类的对象信息.
1. 我们可以用Class.forName()方法动态的根据类名获得一个类的Class对象.
1: /**
2: * 使用此方法为自动初始化静态变量和执行static块的代码3: * 如果找不到对象会抛出一个ClassNotFoundException4: */5: Class second = Class.forName("classLoad.Second");
2. 我们还可以用Class class = ClassName.class 来直接获取一个类的类型信息,但用它和Class.forName()获取类的对象
引用信息在静态块时的执行时间上不同,看下面的例子:
一个普通类信息
1: interface Interface{
2: public static String interFlag = "接口";3:4: }5:6: class Parent implements Interface{7: public static String parntFLAG = "父类静态变量";8: static{
9: final String flag2 = "flag2";//static 区中只能用final修饰10: System.out.println("我在父类静态区里面!"+parntFLAG);
11: }12:13: public Parent(){
14: System.out.println("我在父类构造函数里面!");
15: }16: }17:18:19: class Son extends Parent{20: public static String sonFLAG = "子类类静态变量";21: static{
22: System.out.println("我在子类静态区里面!"+sonFLAG);
23: }24:25: public Son(){
26: System.out.println("我在子类构造函数里面!");
27: }28: }
1: interface Interface{
2: public static String interFlag = "接口";3:4: }5:6: class Parent implements Interface{7: public static String parntFLAG = "父类静态变量";8: static{
9: final String flag2 = "flag2";//static 区中只能用final修饰10: System.out.println("我在父类静态区里面!"+parntFLAG);
11: }12:13: public Parent(){
14: System.out.println("我在父类构造函数里面!");
15: }16: }17:18:19: class Son extends Parent{20: public static String sonFLAG = "子类类静态变量";21: static{
22: System.out.println("我在子类静态区里面!"+sonFLAG);
23: }24:25: public Son(){
26: System.out.println("我在子类构造函数里面!");
27: }28: }
使用这种方法引用类的对象不会始化静态变量和执行静态块信息,这些代码方法会在首次引用时执行.
如下引用父类的静态变量,不会执行子类的静态块.
1: public class ClassLoad {2: public static void main(String[] args) throws ClassNotFoundException {3:4: //Son son = new Son();
5: /**
6: * 我们使用一个类的时候需要进行以下3项工作.7: * 1.加载,8: * 2.链接9: * 3.初始化,此步会初始化静态变量和执行静态块信息,但是这种方法会在10: * 真正调用方法时执行11: */12: Class son = Son.class;
13: System.out.println("静态区的初始化会在调用时执行!");
14: // parntFLAG 是父类的静态变量
15: // 此处只会执行父类的静态快
16: System.out.println(Son.parntFLAG);
17:18: /**
19: * 运行结果20: *静态区的初始化会在调用时执行!21: *我在父类静态区里面!父类静态变量22: *父类静态变量23: */24: }25: }
打印子类的静态变量,所有的代码都会执行
1:2: public class ClassLoad {3: public static void main(String[] args) throws ClassNotFoundException {4:5: //Son son = new Son();
6: /**
7: * 我们使用一个类的时候需要进行以下3项工作.8: * 1.加载,9: * 2.链接10: * 3.初始化,此步会初始化静态变量和执行静态块信息,但是这种方法会在11: * 真正调用方法时执行12: */13: Class son = Son.class;
14: System.out.println("静态区的初始化会在调用时执行!");
15: // parntFLAG 是父类的静态变量
16: // 此处只会执行父类的静态快
17: System.out.println(Son.sonFLAG);
18:19: /**
20: * 运行结果21: * 静态区的初始化会在调用时执行!22: * 我在父类静态区里面!父类静态变量23: * 我在子类静态区里面!子类类静态变量24: * 子类类静态变量25: */26: }27: }
但是使用Class.forName 类加载时就会完成初始化工作.
1: public class ClassLoad {2: public static void main(String[] args) throws Exception {3: /**
4: * 使用Class.forName会自动加载所有静态区的信息5: */6: Class son = Class.forName("classLoad.Son");
7: Son instance = (Son)son.newInstance();8: /*
9: * 执行结果10: * 我在父类静态区里面!父类静态变量11: * 我在子类静态区里面!子类类静态变量12: * 我在父类构造函数里面!13: * 我在子类构造函数里面!14: */15:16: }17: }