Java 反射机制是 Java 自诞生以来就具备的能力,用于在 Java 程序运行过程中动态的获取类的信息,调用类中的方法。
Java 虚拟机将字节码加载到内存中,并且抽象出了一些 Java 类。当程序运行时,可以通过这些类获取字节码中类的元信息。
Java反射的包名为java.lang.reflect
,主要的 UML 类图如下。
反射相关的类主要如下:
其他类如下:
? extend Number
。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 类中常用的方法如下:
方法 | 用途 |
---|---|
public static Class> forName(String className) | 根据类名称获取Class对象 |
public static Class> forName(String name, boolean initialize,ClassLoader loader) | 根据类名称获取Class对象 |
public Package getPackage() | 获取类的包信息 |
public native int getModifiers() | 获取类的修饰符 |
public native Class super T> getSuperclass() | 获取当前类的父类 |
public Type getGenericSuperclass() | 获取泛型父类型 |
public AnnotatedType getAnnotatedSuperclass() | 获取表示当前类的父类的AnnotatedType对象 |
public String getSimpleName() | 获取表示当前类的简单名称 |
public Class>[] getInterfaces() | 获取接口数组 |
public Type[] getGenericInterfaces() | 获取泛型接口数组 |
public AnnotatedType[] getAnnotatedInterfaces() | 获取表示当前类的接口的AnnotatedType数组 |
public Class>[] getClasses() | 获取当前类和其父类公有内部类数组 |
public Class> getDeclaringClass() throws SecurityException | 获取定义当前内部类的外部类,如果当前内部类是匿名内部类返回null |
public XXX> getEnclosingXXX() throws SecurityException | 获取当前匿名内部类所在的类/构造方法/成员方法,XXX 表示 Class/Constructor/Method |
类成员包括内部类、构造方法(Constructor)、成员变量(Field)和成员方法(Method)。
下表中的 XXX 可以表示 Field、Constructor 或者 Method。
方法 | 用途 |
---|---|
public XXX getDeclaredXXX(…) | 获取当前类定义中给定参数指定的成员变量/构造方法/成员方法 |
public XXX[] getDeclaredXXXs() throws SecurityException | 获取当前类定义的所有内部类(Class)/成员变量/构造方法/成员方法 |
public XXX getXXX(…) | 获取当前类及其父类中给定参数的共有成员变量/构造方法/成员方法 (构造方法只获取当前类中定义的) |
public XXX[] getXXXs() throws SecurityException | 获取当前类及其父类中所有共有内部类(Class)/成员变量/构造方法/成员方法 (构造方法只获取当前类中定义的) |
方法 | 用途 |
---|---|
public boolean isAnnotation() | 当前类是否为注解 |
public boolean isAnonymousClass() | 当前类是否为匿名内部类 |
public native boolean isArray() | 当前类是否为数组 |
public native boolean isAssignableFrom(Class> cls) | 当前类是否为给定类的父类 |
public boolean isEnum() | 当前类是否表示枚举类 |
public native boolean isInstance(Object obj) | 当前类是否为给定对象的类型 |
public native boolean isInterface() | 当前类是否表示接口 |
public boolean isLocalClass() | 当前类是否为局部内部类 |
public boolean isMemberClass() | 当前类是否为成员内部类 |
public native boolean isPrimitive() | 当前类是否表示基本数据类型 |
public boolean isSynthetic() | 当前类是否为编译期自动生成的类 |
public native Class> getComponentType() | 获取当前数组类的元素类型 |
public T[] getEnumConstants() | 获取当前枚举类的对象数组 |
public Class extends U> asSubclass(Class clazz) | 将当前Class对象转换为指定Class对象的子类 |
public T cast(Object obj) | 将给定对象转换为当前Class对象表示的类或接口 |
public T newInstance() | 使用当前类的无参构造方法实例化对象 |
public ClassLoader getClassLoader() | 获取当前类的类加载器 |
public String getName() | 获取类的名称 |
public String getCanonicalName() | 获取 Java 语言规范定义的底层类的名称 |
public String toGenericString() | 获取当前类的字符串描述信息 |
Field 通过 Class 的 getDeclaredField(…)、getDeclaredFields()、getField(…) 或者 getFields() 方法获取,主要提供了设置和获取成员变量值的方法。
具体如下,其中XXX可以表示 Boolean、Byte、Char、Short、Int、Long、Float、Double。
方法 | 用途 |
---|---|
public xXX getXXX(Object obj) throws IllegalArgumentException, IllegalAccessException | 获取当前成员变量表示的 Java 基本类型的值 |
public Object get(Object obj) throws IllegalArgumentException, IllegalAccessException | 获取当前成员变量表示的值 |
public void setXxx(Object obj, xxx b) throws IllegalArgumentException, IllegalAccessException | 将当前成员变量设置为给定的 Java 基本类型的值 |
public void set(Object obj, Object value) throws IllegalArgumentException, IllegalAccessException | 将当前成员变量设置为给定的值 |
Constructor 表示构造方法,主要提供了实例化 Java 对象的方法,具体如下。
方法 | 用途 |
---|---|
public T newInstance(Object … initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException | 实例化 Java 对象 |
Method 表示 Java 中的方法,经常用来调用方法,主要的方法如下。
方法 | 用途 |
---|---|
public Object getDefaultValue() | 获取注解中属性的默认值 |
public Type getGenericReturnType() | 获取方法返回泛型类型 |
public Class> getReturnType() | 获取方法返回类型 |
public Object invoke(Object obj, Object… args) | 调用方法 |
public boolean isBridge() | 方法是否为桥接方法 |
public boolean isDefault() | 方法是否为默认方法 |
代码如下:
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){
..
}
}
代码如下:
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
可以看到,私有的方法也可以通过反射进行调用。