Java 高级特性 - 反射机制 (Reflection)

目录

1. 什么是 Java 的反射机制?

2. Java 反射机制用途

2.1 Unsafe 类举例

3. Java 反射机制相关的类

3.1 Class 类及常用方法

3.2 Method 类及其用法

3.3 Field 类及其用法

4. Java 反射使用


1. 什么是 Java 的反射机制?

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。

 

2. Java 反射机制用途

在日常的项目开发过程中,有时会遇到某个类的成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。

2.1 Unsafe 类举例

当我们开发中需要使用 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();
    }
}

 

3. Java 反射机制相关的类

3.1 Class 类及常用方法

该类的实例 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);
}

 

3.2 Method 类及其用法

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);
}

 

3.3 Field 类及其用法

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. Java 反射使用

4.1 定义一个注解 TestAnnotation.java

点击查看 @Retention 注解作用

@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {

    String value() default "";

    String name() default "";
}

4.2 OrderService.javaOrder.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 返回类型一致

成功获取了方法上的注解,并成功输出了注解的两个属性值

你可能感兴趣的:(Java 高级特性 - 反射机制 (Reflection))