目录
1. 什么是 Java 的反射机制?
2. Java 反射机制用途
2.1 Unsafe 类举例
3. Java 反射机制相关的类
3.1 Class 类及常用方法
3.2 Method 类及其用法
3.3 Field 类及其用法
4. Java 反射使用
Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。
在日常的项目开发过程中,有时会遇到某个类的成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。
当我们开发中需要使用 Unsafe 类时,不能直接使用 Unsafe.getUnsafe() 获取 Unsafe 实例。只有当一个类是 Bootstrap ClassLoader 加载的时候,才可以使用。
既然不能通过这种方式获取实例,我们就可以考虑使用 Java 反射机制来使用,代码如下:
static Unsafe unsafe;
static long stateOffset = 0;
private volatile long state = 0;
static {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
stateOffset = unsafe.objectFieldOffset(MyUnsafe.class.getDeclaredField("state"));
} catch (NoSuchFieldException | IllegalAccessException e) {
e.printStackTrace();
}
}
该类的实例 Class 表示正在运行的 Java 应用程序的类和接口。 枚举是一种类、注解是一种接口。
Class 没有公共构造函数。 相反, Class 对象由 Java 虚拟机的类加载并通过调用类加载器中的 defineClass 方法
/**
* 返回Class与类或接口与指定的字符串名称关联的对象。 调用此方法等效于:
* Class.forName(className, true, currentLoader)
* 其中currentLoader表示当前类的类加载器
*/
public static Class> forName(String className)throws ClassNotFoundException {
Class> caller = Reflection.getCallerClass();
return forName0(className, true, ClassLoader.getClassLoader(caller), caller);
}
/**
* 创建此所表示的类的新实例 Class 对象。
*/
public T newInstance()throws InstantiationException, IllegalAccessException{
// 本文只讲解方法的作用,具体代码不再详细列出......
}
/**
* 判断指定Class对象是否是接口类型
*/
public native boolean isInterface();
/**
* 判断指定Class对象是否是数组类型
*/
public native boolean isArray();
/**
* 判断指定Class对象是否是基本类型
*/
public native boolean isPrimitive();
/**
* 判断指定Class对象是否是注解类型
*/
public boolean isAnnotation() {
return (getModifiers() & ANNOTATION) != 0;
}
/**
* 以字符串的形式返回该类所表示的实体
* (类,接口,数组类,基本类型,或 void)
* 返回完整的路径名称
*/
public String getName() {
String name = this.name;
if (name == null)
this.name = name = getName0();
return name;
}
/**
* 返回类名
*/
public String getSimpleName() {
......
}
/**
* 返回该类的类加载器
*/
public ClassLoader getClassLoader() {
ClassLoader cl = getClassLoader0();
if (cl == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(cl, Reflection.getCallerClass());
}
return cl;
}
/**
* 以数组的形式返回该类中的所有的 Field 对象
* 包括 public,protected,默认的 package 和 private,但不包括继承的字段
*/
public Field[] getDeclaredFields() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyFields(privateGetDeclaredFields(false));
}
/**
* 以数组的形式返回该类中的所有的 Method 对象
* 包括 public,protected,默认的 package 和 private,但不包括继承的字段
*/
public Method[] getDeclaredMethods() throws SecurityException {
checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true);
return copyMethods(privateGetDeclaredMethods(false));
}
/**
* 以数组的形式返回该类中的 public 的 Method 对象
*/
public Method[] getMethods() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyMethods(privateGetPublicMethods());
}
/**
* 以数组的形式返回该类中的 public 的 Field 对象
*/
public Field[] getFields() throws SecurityException {
checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true);
return copyFields(privateGetPublicFields(null));
}
/**
* 以数组形式返回 Class 对象上的所有注解
*/
public Annotation[] getAnnotations() {
return AnnotationParser.toArray(annotationData().annotations);
}
/**
* 返回该 Class 上的指定注解,没有该注解则返回 null
*/
public A getDeclaredAnnotation(Class annotationClass) {
Objects.requireNonNull(annotationClass);
return (A) annotationData().declaredAnnotations.get(annotationClass);
}
Method 代表类的方法
/**
* 调用 obj 的该方法对象,并传入相关参数
*/
public Object invoke(Object obj, Object... args)throws IllegalAccessException,
IllegalArgumentException, InvocationTargetException{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
MethodAccessor ma = methodAccessor;
if (ma == null) {
ma = acquireMethodAccessor();
}
return ma.invoke(obj, args);
}
/**
* 以数组形式返回 Class 对象上的所有注解
*/
public Annotation[] getDeclaredAnnotations() {
return super.getDeclaredAnnotations();
}
/**
* 返回该 Method 上的指定注解,没有该注解则返回 null
*/
public T getAnnotation(Class annotationClass) {
return super.getAnnotation(annotationClass);
}
Field 代表类的成员变量(类的属性)
/**
* 设置 obj 中对应属性值为 value
* 相关类:
* setInt(Object obj, int i) 等效 (Object obj, Object value) value 为 int 类型
* setFloat(Object obj, float f) 等效 (Object obj, Object value) value 为 float 类型
* ......
*/
public void set(Object obj, Object value)throws IllegalArgumentException, IllegalAccessException{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
getFieldAccessor(obj).set(obj, value);
}
/**
* 返回该 obj 中对应属性值
*/
public Object get(Object obj)throws IllegalArgumentException, IllegalAccessException{
if (!override) {
if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
Class> caller = Reflection.getCallerClass();
checkAccess(caller, clazz, obj, modifiers);
}
}
return getFieldAccessor(obj).get(obj);
}
/**
* 比较 field 与 obj 是否相同,相同则返回 true
* 相同的判断条件:它们是由相同的类声明并且具有相同的名称和类型
*/
public boolean equals(Object obj) {
if (obj != null && obj instanceof Field) {
Field other = (Field)obj;
return (getDeclaringClass() == other.getDeclaringClass())
&& (getName() == other.getName())
&& (getType() == other.getType());
}
return false;
}
4.1 定义一个注解 TestAnnotation.java
点击查看 @Retention 注解作用
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
String value() default "";
String name() default "";
}
4.2 OrderService.java 和 Order.java 类
OrderService 中有一个名为 getOrderById 的方法,传入一个 int 型的参数。方法上添加了自定义的 @TestAnnotation 注解。
注解属性 value 的值为 values,name 的值为 hello world
public class OrderService{
@TestAnnotation(value = "values",name = "hello world")
public Order getOrderById(int id) {
Order order = new Order();
order.setDescription("order");
order.setOrderId(id);
order.setOrderTime(new Date());
return order;
}
}
public class Order {
private int orderId;
private Date orderTime;
private String description;
// get/set
}
4.3 反射调用
public static void main(String[] args) throws Exception {
// 获取 class
Class> orderClass = Class.forName("cmos.service.OrderService");
// 实例对象
Object orderInstance = orderClass.newInstance();
// 获取名称为 getOrderById,参数类型为 1 个 int 型的方法
Method method = orderClass.getMethod("getOrderById", int.class);
method.setAccessible(true);
// 执行方法,参数传 123,拿到返回的 result
Object result = method.invoke(orderInstance, 123);
System.out.println("result.getClass() = " + result.getClass());
// 获取方法上到 TestAnnotation 注解
TestAnnotation testAnnotation = method.getAnnotation(TestAnnotation.class);
if (testAnnotation != null) {
// 注解不为 null,输出注解的两个属性值
System.out.println("annotation.name() = " + testAnnotation.name());
System.out.println("annotation.value() = " + testAnnotation.value());
}
}
执行 main 方法,控制台输出内容如下:
result.getClass() = class cmos.service.Order
annotation.name() = hello world
annotation.value() = values
可见我们通过 Java 反射成功执行了方法,返回的 result 为 Order 类型,与我们定义的 getOrderById 返回类型一致
成功获取了方法上的注解,并成功输出了注解的两个属性值