什么是Java反射?
Java 反射机制是 Java 自诞生以来就具备的能力,用于在 Java 程序运行过程中动态的获取类的信息,调用类中的方法。
Java 反射的使用场景
获取类的信息:如 Spring 中通过读取类的注解信息注册 Bean 对象。
调用类的方法:Spring 可以读取 XML 的配置信息,选择恰当的构造器,通过反射实例化 Bean 对象。
Java 反射机制提供了哪些 API ?
Java 虚拟机将字节码加载到内存中,并且抽象出了一些 Java 类。当程序运行时,可以通过这些类获取字节码中类的元信息。
Java反射的包名为java.lang.reflect,主要的 UML 类图如下。
反射相关的类主要如下:
Class:表示Java类。
Field:表示Java类中的成员变量。
Method:表示Java类中的成员方法。
Constructor:表示Java类的构造方法。
其他类如下:
Array:表示数组。
AnnotatedElement:JDK 1.5 新增,泛型相关,表示可以被注解标注的元素,如类、成员变量、
方法等。
Member:表示 Java 类中的成员,如成员变量,成员方法,构造方法。
AccessibleObject:JDK 1.2 新增,Field、Method、Constructor的父接口,提供对反射对象抑制默认的 Java 访问控制检查的能力。
GenericDeclaration:JDK 1.5 新增,泛型相关,表示可以定义类型变量的元素。
Type:JDK 1.5 新增,表示 Java 中的某一种类型。
Parameter:JDK 1.8 新增,表示成员方法或构造方法中的某一个参数。
AnnotatedType:JDK 1.8 新增,表示可以被注解标注的类型。
Executable:JDK 8 新增,Method 和 Constructor 的父接口。
TypeVariable:JDK 1.5 新增,泛型相关,类型变量,如List 中的 T。
GenericArrayType:JDK 1.5 新增,泛型相关,泛型数组类型,如 T[] 。
ParameterizedType:JDK 1.5 新增,泛型相关,参数化类型,如 Class 。
WildcardType:JDK 1.5 新增,泛型相关,通配符类型,如 Class 中的 ? extend Number。
Class 类
Class 类表示 Java 中的某一个类,不包含类的泛型信息。
获取方式主要有三种,如下:
java.lang.Class#forName(java.lang.String):如 Class cls = Class.forName("com.mysql.cj.jdbc.Driver")。
java.lang.Object#getClass:如 Class cls = "hello,java".getClass()。
Type.class:如 Class cls = String.class。
Class 类中常用的方法如下:
类定义相关方法
类成员相关方法
类成员包括内部类、构造方法(Constructor)、成员变量(Field)和成员方法(Method)。
下表中的 XXX 可以表示 Field、Constructor 或者 Method。
其他方法
Field 类
Field 通过 Class 的 getDeclaredField(…)、getDeclaredFields()、getField(…) 或者 getFields() 方法获取,主要提供了设置和获取成员变量值的方法。
具体如下,其中XXX可以表示 Boolean、Byte、Char、Short、Int、Long、Float、Double。
Constructor 类
Constructor 表示构造方法,主要提供了实例化 Java 对象的方法,具体如下。
Method 类
Method 表示 Java 中的方法,经常用来调用方法,主要的方法如下。
反射使用示例
示例1,打印给定类的结构
代码如下:
package com.zzuhkp; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; import java.util.Arrays; import java.util.stream.Collectors; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * @author zzuhkp * @date 2020-08-05 9:48 * @since 1.0 */ public class ReflectTest { @NotBlank(message = "名称不能为空") private String name; public static void main(String[] args) { printClass(ReflectTest.class); } @Deprecated public static void printClass(@NotNull Class<?> cls) { StringBuilder sb = new StringBuilder(); // 获取包信息 Package aPackage = cls.getPackage(); if (aPackage != null) { sb.append("package ").append(aPackage.getName()).append(";\n\n"); } // 获取类修饰符信息 String modifier = Modifier.toString(cls.getModifiers()); if (modifier.length() > 0) { sb.append(modifier).append(" "); } // 获取类名 sb.append("class ").append(cls.getSimpleName()).append(" "); // 获取父类 Type superclass = cls.getGenericSuperclass(); if (superclass != Object.class) { sb.append("extend ").append(superclass.getTypeName()).append(" "); } // 获取接口 Type[] interfaces = cls.getGenericInterfaces(); if (interfaces.length > 0) { String interfaceStr = Arrays.stream(interfaces).map(Type::getTypeName).collect(Collectors.joining(",")); sb.append("implements ").append(interfaceStr).append(" "); } sb.append("{\n\n"); // 获取成员变量 Field[] fields = cls.getDeclaredFields(); for (Field field : fields) { //获取成员变量的注解 for (Annotation annotation : field.getAnnotations()) { sb.append(" ").append(annotation).append("\n"); } // 获取成员变量修饰符 String fieldModifier = Modifier.toString(field.getModifiers()); // 获取成员变量类型名称 String fieldTypeName = field.getGenericType().getTypeName(); // 获取成员变量名称 String fieldName = field.getName(); sb.append(" ").append(fieldModifier).append(" ").append(fieldTypeName) .append(" ").append(fieldName).append(";\n"); } sb.append("\n"); Constructor<?>[] constructors = cls.getDeclaredConstructors(); for (Constructor<?> constructor : constructors) { for (Annotation annotation : constructor.getAnnotations()) { sb.append(" ").append(annotation).append("\n"); } sb.append(" "); // 获取构造方法修饰符 int constructorModifiers = constructor.getModifiers(); String methodModifier = Modifier.toString(constructorModifiers); if (methodModifier.length() > 0) { sb.append(methodModifier).append(" "); } // 获取构造方法名称 String constructorName = constructor.getName(); sb.append(constructorName).append("("); // 获取方法参数 String parameters = Arrays.stream(constructor.getParameters()) .map(parameter -> { // 获取方法参数注解 String str = Arrays.stream(parameter.getAnnotations()).map(Annotation::toString) .collect(Collectors.joining(" ")); if (str.length() > 0) { str = str + " "; } // 获取方法参数类型及名称 str = str + parameter.getParameterizedType().getTypeName() + " " + parameter.getName(); return str; }) .collect(Collectors.joining(",")); sb.append(parameters); sb.append(")"); if (!Modifier.isNative(constructorModifiers)) { sb.append("{\n").append(" ..\n").append(" }"); } else { sb.append(";"); } sb.append("\n"); } // 获取成员方法 Method[] methods = cls.getDeclaredMethods(); for (Method method : methods) { for (Annotation annotation : method.getAnnotations()) { sb.append(" ").append(annotation).append("\n"); } sb.append(" "); // 获取成员方法修饰符 int methodModifiers = method.getModifiers(); String methodModifier = Modifier.toString(methodModifiers); if (methodModifier.length() > 0) { sb.append(methodModifier).append(" "); } // 获取成员方法返回值类型 String returnType = method.getGenericReturnType().getTypeName(); sb.append(returnType).append(" "); // 获取成员方法名称 String methodName = method.getName(); sb.append(methodName).append("("); // 获取方法参数 String parameters = Arrays.stream(method.getParameters()) .map(parameter -> { // 获取方法参数注解 String str = Arrays.stream(parameter.getAnnotations()).map(Annotation::toString) .collect(Collectors.joining(" ")); if (str.length() > 0) { str = str + " "; } // 获取方法参数类型及名称 str = str + parameter.getParameterizedType().getTypeName() + " " + parameter.getName(); return str; }) .collect(Collectors.joining(",")); sb.append(parameters); sb.append(")"); if (!Modifier.isNative(methodModifiers)) { sb.append("{\n").append(" ..\n").append(" }"); } else { sb.append(";"); } sb.append("\n"); } sb.append("}"); System.out.println(sb); } }
执行结果如下:
package com.zzuhkp; public class ReflectTest { @javax.validation.constraints.NotBlank(message=名称不能为空, groups=[], payload=[]) private java.lang.String name; public com.zzuhkp.ReflectTest(){ .. } public static void main(java.lang.String[] args){ .. } private static java.lang.String lambda$printClass$1(java.lang.reflect.Parameter parameter){ .. } @java.lang.Deprecated() public static void printClass(@javax.validation.constraints.NotNull(message={javax.validation.constraints.NotNull.message}, groups=[], payload=[]) java.lang.Class<?> cls){ .. } private static java.lang.String lambda$printClass$0(java.lang.reflect.Parameter parameter){ .. } }
示例2,通过反射调用方法
代码如下:
public class ReflectTest { static class Test { private void sayHello() { System.out.println("你好,Java"); } } public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Test test = new Test(); Method method = Test.class.getDeclaredMethod("sayHello"); method.setAccessible(true); method.invoke(test); } }
执行结果如下:
你好,Java
可以看到,私有的方法也可以通过反射进行调用。