RTTI(Runtime Type Information),运行时类型信息使得你可以在程序运行时发现和使用类型信息。
- 14.2 Class对象
类是程序的一部分,每个类都有一个Class对象。换言之,每当编写并且编译了一个新类,就会产生一个Class对象(更恰当地说,是被保存在一个同名的.class文件中)。为了生成这个类的对象,运行这个程序的Java虚拟机(JVM)将使用被称为“类加载器”的子系统。
Java程序在它开始运行之前并非被完全加载,其各个部分是在必需时才加载的。所有的类都是在对其第一次使用时,动态加载到JVM中的。当程序创建第一个对类的静态成员的引用时,就会加载这个类。(这个证明构造器也是类的静态方法)
获得Class对象的引用的几种方法:
- Class.forName(“typeinfo.toys.FancyToy”)。—传递给forName()的字符串中,必须使用全限定名(包含包名),并且注意大小写。
- 类字面常量:FancyToy.class。—这样做不仅更简单,而且更安全,因为它在编译时就会收到检查(不需要放在try语句中)。==注意,当使用“.class”来创建对Class对象的引用时,不会自动地初始化改Class对象。==类字面常量不仅可以应用于普通的类,还可以应用于接口、数据以及基本数据类型。另外,对于基本数据类型的包装器类,还有一个标准字段TYPE,TYPE字段是一个引用,指向对应的基本数据类型的Class对象,如:boolean.class等价于Boolean.TYPE.
- obj.getClass()
为了使用类而做的准备工作实际包含以下三个步骤:
- 加载。这是由类加载器执行的。该步骤将查找字节码(通常在classpath所指定的路径中茶盅,但这并非是必须的),并从这些字节码中创建一个Class对象。
- 链接。在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必需的话,将解析这个类创建的对其他类的所有引用。
- 初始化。如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块。
初始化被延迟到了对静态方法(构造器隐式的是静态的)或者非常数静态域进行首次引用时才执行:
static void callHiddenMethod(Object a, Strign methodName) throws Exception{ Method g = a.getClass().getDeclaredMethod(methodName); g.setAccessible(true); g.invoke(a); }
不管是将接口实现为一个私有内部类:
//InnerA$C class InnerA{ private static class C implements A{ //... } public static A makeA(){ return new C(); } }
还是匿名类:
//AnonymousA$1 class AnonymousA(){ public static A makeA(){ return new A(){ //.... } } }
都无法阻止反射到达并调用那些非公共访问权限的方法,对于域来说,即便是private域。
但是,final域在遭遇修改时是安全的,运行时系统会在不抛异常的情况下接受任何修改尝试,但是实际上不会发生任何修改。
class WithPrivateFinlaField{ private final String s = "I'm totally safe";//用反射无法修改 }
相关文章