1、Class.forName()方法就是可以取得Class对像的引用的一种方法。用此方法加载进来的类信息包含很多的方法,能够知道该类具体是什么类型名称是什么等信息。
2、类字面常量的方法也能够生成Class对像的引用。类字面常量方法加载类更加安全,因为该方法在编译的时候就检查了类。
普通类、接口、数组、基础数据类型都可以使用。
boolean.class Boolean.class
char.class Character.claa
byte.class Byte.class
类字面常量这个方法不会给类初始化。
那么一个类真正可以使用需要经过三个步骤:
1、 加载。类加载器执行。
2、链接。将叫类连接阶段将验证类中的字节码,为静态与分配存储空间,如果有必要的话,将解释该类创建的对其它类的所有引用。
3、初始化。如果该类具有超类,对其初始化,执行讲台初始化器和静态初始化块儿。
初始化被延迟到了对静态方法或者非常数静态域进行首次引用时才执行。
.class不会进行初始化,
package thinkinjava.characterforclass;
import java.util.Random;
public class ClassInitialization {
public static Random rand=new Random(47);
public static void main(String[] args) throws Exception{
Class initable=Initable.class;//没有初始化
System.out.println("after creating Initable ref");
System.out.println(Initable.staticFinal1);// 先打印出了静态常量,然后是静态初始化块儿
System.out.println(Initable.staticFinal2); //打印出了静态常量2
System.out.println(Initable2.staticNonFinal); //先打印了静态初始化块儿,然后打印静态常量
Class initable3=Class.forName("thinkinjava.characterforclass.Initable3"); //进行了类的三个步骤:加载、连接、初始化。
System.out.println("After creating Initable3 ref");
System.out.println(Initable3.staticNonFinal);
}
}
static final int staticFinal1=47;//编译器就能够确定的常量 ,不需要运行静态初始化就能够确定下来的。
static final int staticFinal2=ClassInitialization.rand.nextInt(1000); //编译器才能够确定的量,这个需要运行才能够确定下来。
static int staticNonFinal=47;//对这种数据访问,要进行链接(为这个域分配存储空间),和初始化(初始化该存储空间)。
知道运行时的类信息有两种手段,第一种就是RTTI、第二种就是反射机制。
RTTI
1、传统的类型转换由RTTI去报类型转换的正确性。
2、代表对像的类型的Class对像。通过方法可以知道类信息。
3、instanceof方法
要想在动态执行某个类的方法一定提前用这个方法
if(x instanceof Dog){
((Dog)x).bark();
}
反射: 在.class文件编译时无法获取,所以实在运行打开和检查.class文件。
反射支持了其他特性:对像序列化、javaBean