。class文件即类的class对象,class对象可以拿到要了解的类型的所有信息。
所有的类都是在对其第一次使用时,动态加载到jvm当程序创建第一个对类的静态成员的引用时,就会加载这个类。证明构造器也是类的静态方法。static块初始化是在类加载时进行的。
一、
取得类的对象的引用:
1、Class.forName(类的完全限定名)
通过class对象引用,1).getName() 取得完全限定名 2).getSimpleName() 取得类名 3).getCanonicalName() 取得完全限定名 4).isInterface() 判断是否是接口
5).getInterfaces() 得到实现的所有接口 6).getSuperClass() 得到继承的父类
2、类名.class 类字面常量,在编译时检查,不需要像1放在try中,可用于所有类甚至基本类型。
基本类型对应包装器类型的TYPE字段: char.class === Boolean.TYPE void.class === Void.TYPE
使用.class创建Class对象的引用时,不会自动初始化该Class对象。
为使用类需要做三步准备工作:1)加载。 类加载器从classpath指定path(非必需)查找字节码然后创建Class对象
2)链接。验证类中字节码,为静态域分配存储空间,若必需,解析对其他类的所有引用
3)初始化。若该类有超类,则对其初始化,执行静态初始化器和静态初始化块。
static final值是编译期常量,无需初始化。 static且非final的值在第一次读取时会链接(为此域分配空间)并初始化class对象。
二、
泛化的Class引用
1、通过使用泛型语法,可以让编译期强制执行额外的类型检查。
如:
Class intClass = int.class
Class<Integer> genericIntClass = int.class
genericIntClass = Integer.class
intClass = double.class
genericIntClass = double.class// Illegal
2、通配符在泛型中指定范围
Class<?> 代表所有,但由于普通Class,不会产生编译器警告
Class<? extends Number> bounded = int.class
bounded = double.class
bounded = Number.class.....
3、class对象引用.newInstance() 产生对象的精确类型。
但是如果是获取超类:
Class<? super 子类> up = 子类class引用.superClass()
Object obj = up.newInstance(); //-------->拿到的是不精确类型Object