5.7 反射
反射库(reflection library)
:提供了一个非常丰富且精心设计的工具集,以便编写能够动态操纵Java代码的程序
反射(reflection)
:能够分析类的能力的程序- 在运行时分析类的能力
- 在运行时查看对象
- 实现通用的数组操作代码
- 利用
Method对象
,类似于C++中的函数指针
5.7.1 Class类
- 在程序运行期间,Java运行时系统始终未所有对象维护一个被称为
运行时
的类型标识- 该信息跟踪着每个对象所属的类.
- 虚拟机利用运行时类型信息选择相应的方法执行
Class类
:用于访问运行时类型信息的类Ojbect类中的getClass()
将会返回一个Class类型的实例- 一个Class对象将表示一个特定类的属性
- 如果类在一个包里,
包的名字也作为类名的一部分
- 可以调用
静态方法forName
获取类名对应的Class对象- 如果
类名保存在字符串中,并可以在运行中改变
,就可以使用该方法, 否则将抛出一个CheckedException(已检查异常)
- 无论何时使用该方法,都应该提供一个
异常处理器(exception handler)
- 如果
- 在启动时,包含main方法的类被加载.它会加载所有需要的类.这些被加载的类又要加载它们需要的类,
以此类推.这将消耗很多时间.
可以先显示一个启动画面,然后通过Class.forName手工加载其他类
. 这样会给用户一种启动速度比较快的幻觉(>_<) 幻觉...
- 一个Class对象实际上表示的是一个类型,而该类型未必是一个类
- Class类实际上是一个
泛型类
- 虚拟机为每个类型管理一个Class对象.因此可以使用
==运算符
实现两个类对象比较 newInstance()
: 用于动态创建一个类的实例.- newInstance()调用默认的无参构造器初始化新创建的对象
- 如果类没有默认构造器,将会抛出异常
forName方法
和newInstance方法
配合使用,可以根据存储在字符串中的类名创建一个对象
5.7.2 捕获异常
- 当程序运行过程中发生错误,就会
抛出异常
- 抛出异常比终止程序要灵活得多,因为可以提供
捕获异常的处理器(handler)
- 如果没有处理器,程序就会终止,并且在控制台上输出一条信息,其中给出了异常的类型
- 抛出异常比终止程序要灵活得多,因为可以提供
- 异常有两种,
未检查
和已检查
异常- 对于
已检查异常
,编译器将会检查是否提供了处理器
- 对于
- 将可能抛出已检查异常的一个或多个方法调用代码放在
try块
中,然后在catch字句
中提供处理器代码try{ statements that might throw exceptions } catch(Exception e){ handler action }
- 对于已检查异常,只需要提供一个异常处理器.
- 如果调用了一个抛出已检查异常的方法,而又没有提供处理器,编译器就会给出错误报告
API | 所在包 | 描述 | 参数以及描述 |
---|---|---|---|
static Class forName(String className) |
java.lang.Class |
返回类名为className的Class对象 | |
Object newInstance() |
java.lang.Class |
返回这个类的一个新实例 | |
Object newInstance(Object[] args) |
java.lang.reflect.Constructor |
构造一个这个构造器所属类的新实例 | args : 这是提供构造器的参数 |
void printStackTrace() |
java.lang.Throwable |
将Throwable对象和栈轨迹输出到标准错误流 |
5.7.3 利用反射分析类的能力
API | 所在包 | 描述 | 参数与描述 |
---|---|---|---|
Field[] getFields() Field[] getDeclared() |
java.lang.Class |
getFields方法 将返回一个包含Field对象的数组,这些对象 记录了这个类和其父类公有域 getDeclared方法 也将返回包含Field对象的数组,这些对象 记录了这个类的全部域 |
如果类中没有域 ,或者Class对象 描述的是基本类型或者数组类型 这些方法将 返回一个长度为0的数组 |
Method[] getMethods() Method[] getDeclareMethods() |
java.lang.Class |
返回包含Method对象的数组 getMethods将返回所有的公共方法, 包括从父类继承来的公有方法 getDeclareMethods返回这个类或接口的全部方法, 但不包括由父类继承来的方法 |
|
Constructor[] getConstructors() Constructor[] getDeclareContructors() |
java.lang.Class |
返回包含Constructor对象的数组 其中包含了Class对象所描述的 公有构造器(getConstructors) 和所有构造器(getDeclaredConstructors) |
|
Class getDeclaringClass() |
java.lang.reflect.Field java.lang.reflect.Method java.lang.reflect.Constructor |
返回一个用于描述类中定义的构造器、方法或域的Class对象 | |
Class[] getExceptionTypes() |
java.lang.reflect.Field java.lang.reflect.Method java.lang.reflect.Constructor |
返回一个用于描述方法抛出的异常类型的Class对象数组 | |
int getModifiers() |
java.lang.reflect.Field java.lang.reflect.Method java.lang.reflect.Constructor |
返回一个用于描述构造器、方法或域的修饰符的整形数值. 使用 Modifier类 中的这个方法可以分析这个返回值 |
|
String getName() |
java.lang.reflect.Field java.lang.reflect.Method java.lang.reflect.Constructor |
返回一个用于描述构造器、方法或域名的字符串 | |
Class[] getParamterTypes() |
java.lang.reflect.Field java.lang.reflect.Method java.lang.reflect.Constructor |
返回一个用于描述参数类型的Class对象数组 | |
Class getReturnType() |
java.lang.reflect.Field java.lang.reflect.Method java.lang.reflect.Constructor |
返回一个用于描述返回类型的Class对象 | |
static String toString(int modifier) |
java.lang.reflect.Modifier |
返回对应modifiers中位设置的修饰符的字符串表示 | |
static boolean isAbstract(int modifiers) static boolean isFinal(int modifiers) static boolean isInterface(int modifiers) static boolean isNative(int modifiers) static boolean isPrivate(int modifiers) static boolean isProtected(int modifiers) static boolean isPublic(int modifiers) static boolean isStatic(int modifiers) static boolean isStrcit(int modifiers) static boolean isSynchronized(int modifiers) static boolean isVolatile(int modifiers) |
java.lang.reflect.Modifier |
这些方法将检测方法名中对应的修饰符在modifiers值中的位 |
5.7.4 在运行时使用反射分析对象
- 查看任意对象的数据域名称和类型:
- 获得对应的Class对象
- 通过Class对象调用getDeclaredFields
API | 所在包 | 描述 | 参数与描述 |
---|---|---|---|
void setAccessible(boolean flag) |
java.lang.reflect.AccessibleObject |
为反射对象设置可访问标志 | flag :true表明屏蔽Java语言的访问检查,使得对象的私有属性也可以被查询和设置 |
boolean isAccessible() |
java.lang.reflect.AccessibleObject |
返回反射对象的可访问标志的值 | |
static void setAccessible(AccessibleObject[] array,boolean flag) |
java.lang.reflect.AccessibleObject |
是一种设置对象数组可访问标志的快捷方法 | |
Field getField(String name) Field[] getField() |
java.lang.Class |
返回指定名称的公有域,或包含所有域的数组 | |
Field getDeclaredField(String name) Field[] getDeclaredFields() |
java.lang.Class |
返回类声明中的给定名称的域,或者包含声明的全部域的数组 | |
Object get(Object obj) |
java.lang.reflect.Field |
返回obj对象中Field对象表示的域值 | |
void set(Object obj,Object newValue) |
java.lang.reflect.Field |
用一个新值设置obj对象中Field对象表示的域 |
5.7.5 使用反射编写泛型数组代码
java.lang.refelect
包中的Array
类允许动态创建数组- Array类中的静态方法
newInstance
能够构造新数组,- 必须提供两个参数:一个是
数组的元素类型
,一个是数组的长度
- 必须提供两个参数:一个是
- Array类的静态方法
getLength
能够返回数组长度- 首先获得数组的类对象
- 确认是一个数组
- 使用Class类的
getComponentType
方法确定数组对应的类型
API | 所在包 | 描述 |
---|---|---|
static Object get(Object array,int index) static [primitiveTypes] get[primitiveTypes](Object array,int index) |
java.lang.reflect.Array |
[primitiveTypes]是boolean,byte,char,double,float,int,long,short之中的一种基本类型 这些方法将返回存储在指定位置上的数组内容 |
static void set(Object array,int index,Object newValue) static set[primitiveTypes](Object array,int index,[primitiveTypes] newValue) |
java.lang.reflect.Array |
[primitiveTypes]是boolean,byte,char,double,float,int,long,short之中的一种基本类型 这些方法将一个新值存储到指定的位置上面 |
static int getLength(Object array) |
java.lang.reflect.Array |
返回数组的长度 |
static Object newInstance(Class componentType,int length) static Object newInstance(Class componentType,int[] lengths) |
java.lang.reflect.Array |
返回一个具有给定类型、给定维数的新数组 |
5.7.6 调用任意方法
- 建议Java开发着
不要使用Method对象的回调功能
使用接口进行回调
会使得代码的执行速度更快更利于维护
API | 所在包 | 描述 |
---|---|---|
public Object invoke(Object implicitParameter,Object[] explictParameters) |
java.lang.reflect.Method |
调用这个方法所描述的方法,传递给定参数,并返回方法的返回值 |