反射简介
能够分析类能力的程序成为反射(reflective)。
反射可以用来干什么?
反射经常用于构建库或工具,主要包含以下能力:
- 运行时分析类的能力;
- 运行时查看对象,如编写一个toString查看对象属性;
- 实现通用的数组操作代码;
- 利用Method对象,类似于C/C++函数指针;
Class类
主要作用:维护Java对象类型信息 -- 程序运行时,Java运行时系统始终为所有对象维护一个被成为运行时的类型标识。该信息跟踪者每个对象所属的类。虚拟机利用运行时类型信息选择相应方法执行。
保存这些维护类型信息的类称为Class。
获取Class类对象
如何获取Class类对象?
有3种方法:
- 对象的getClass()方法;
- Class静态方法Class.forName();
- 类名.class;
示例:
// 方法1: 一个类的对象 -> Class类对象
Employee e;
Class c = e.getClass(); // 通过getClass(), 获取对象e的类型信息
// 方法2: 类名称: -> Class 类对象
String className = "java.util.Random"; // 类名(需要包含包的路径)
Class c2 = Class.forName(className) ; // 通过Clas静态方法forName(),
// 方法3: 类名.class -> Class类对象
Class random = Random.class;
Class cint = int.class;
Class cdoubles = Double[].class;
Class类包含哪些类的信息?
- 类名;
- 创建类的实例;
- 比较类型信息;
读取类名
Class的getName方法可以读取类名,包也作为类名的一部分
System.out.println(e.getClass.getName() + " " + e.getName());
创建类的实例
Class对象的newInstance方法
// 根据不同获取Class对象方式, 分为三种方式, 不过都是调用Class对象的newInstance方法
// 方式一
Employee e = new Employee();
e.getClass().newInstance();
// 方式二
String s = "java.util.Random";
Object m = Class.forName(s).newInstance();
// 方式三
Object m = Integer.class.newInstance();
比较类型信息"=="
类似于Ojective-C的内省方法,可以用 “==”检查某个类对象是否为指定类对象。
如,
// 检查e的Class对象是否为Employee类对象
Employee e;
if(e.getClass() == Employee.class) {
..
}
// 检查e的父对象是否为Object类对象
Employee e;
Class cl = e.getClass();
Class supercl = cl.getSupperClass();
if (supercl == Object.class) {
// process e or cl
}
捕获异常
如果类名对应类不存在,用forName()创建Class对象会抛出异常ClassNotFoundException。简单处理方式,如下
try {
Claass c1 = Class.forName("TestNotExistClass");
// do sth. with c1
}catch(Exception e) {
e.printStackTrace();
}
反射分析类
- 字段类:Field,提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。;
- 方法类:Method;
- 构造器类:Constructor;
- 修饰符工具类:Modifiers;
Field 字段类型类, Method 方法类型类, Constructor 构造器类
java.lang.reflect包有三个类Field、Method、Constructor分别用于描述类的域(字段)、方法、构造器。
三个类都有getName()方法,返回项名称。
Field类有getType方法,返回域所属类型的Class对象。
Method类和Constructor类有能够报告参数类型的方法。
Method类getReturnType方法能报告函数返回值类型。
Class常用方法
Field[] getFields(); // 返回包含Field对象的数组,记录了类或其超类的公有域
Field[] getDeclaredFields(); // 返回包含Field对象的数组,记录了类的所有域(不包括超类)
Method[] getMethods(); // 返回包含Method对象的数组,记录了类或其超类的公有方法
Method[] getDeclaredMethods(); // 返回包含Method对象的数组,记录了类的所有方法(不包括超类)
Constructor[] getConstructors(); // 返回包含Constructor对象的数组,记录了类或其超类的公有构造器
Constructor[] getDeclareConstructor(); // 返回包含Constructor对象的数组,记录了类的所有构造器(不包括超类)
Class getClass(); // 获取对象或者类的Class对象
Class getSuperclass(); // 获取对象或者类的父类Class对象
Class getName(); // 获取对象或类的名称(字符串)
static Class forName(String); // 根据路径创建Class对象
TypeVariable[] getTypeParameters(); // 获取声明的变量类型的数组
int getModifiers(); // 获取对象或类的的Java语言修饰符(如public, static)使用情况
Field、Method、Constructor常用方法
Class getType(); (Field独有) // 获取域的类型
Class getReturnType(); (Method独有) // 获取返回值类型
Class[] getExceptionTypes(); (Constructor和Method类中) // 描述方法抛出的异常类型数组
Class[] getParameterTypes(); (Constructor和Method类中) // 描述参数类型的Class对象数组
Object get(Object obj); // 获取obj对象中Field对象表示的值, 调用对象是Field对象(即要获取的属性),obj对象是要查询的属性值所属类对象. 也就是说,返回obj.调用对象的Field值
void set(Object obj, Object newValue); // 设置obj.调用对象所属Field = newValue
Class getDeclaringClass(); // 返回用于描述类中定义的Constructor、Method或Field的类型
Class getName(); // 获取名称
int getModifiers(); // 获取修饰符使用情况
void setAccessible(boolean ); // 修改反射对象的访问标志 (为调试、持久存储和相似机制提供的功能)
boolean isAccessible(); // 查询反射对象可访问标志
Modifiers 修饰符工具类
Field、Method、Constructor三个类都有getModifiers方法,返回一个整型值,不同的位代表public static等修饰符使用情况。
可以利用java.lang.reflect包中的Modifier类的静态分析getModifiers返回的整型值,如使用Modifier类的isPublic、isPrivate、isFinal判断方法或构造器是否是public、private或final。
Modifiers.toString() 将修饰符打印出来。
获取Field, Method, Constructor
Class类的getFields、getMethods和getConstructors方法返回类的public 域、方法和构造器数组。(所有的public成员,包括超类的public成员)
Class类的getDeclareFields、getDeclareMethods、getDeclareConstructorsf方法返回类类的所有域、方法和构造器数组。(所有的public、private、protected成员,但不包括超类的成员)
Modifiers 常用方法
static String toString(int modifiers); // 读取modifilers中设置的修饰符使用情况的字符串表示
// 读取是否为函数名对应修饰符修饰
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 isStrict(int modifiers);
static boolean isSynchronized(int modifiers);
static boolean isVolatile(int modifiers);