跳到主要内容
Java 反射详解 | 极客日志
Java java
Java 反射详解 综述由AI生成 详细讲解了 Java 反射机制,涵盖 Class 类获取方式、Constructor 构造器操作、Field 成员变量操作、Method 方法调用以及 Annotation 注解解析。内容包含各类 API 说明、代码示例及实战练习题,帮助读者理解如何通过反射在运行时动态获取和操作类信息,突破编译期限制,是掌握 Spring 等框架底层原理的基础。
微码行者 发布于 2026/3/30 更新于 2026/5/20 26 浏览1. 反射概述
1.1 什么是反射
反射(Reflection)是 Java 提供的强大特性,允许程序在运行时 动态地获取、访问类的所有信息(包括类名、属性、方法、构造器、注解等),并能动态操作这些信息,突破编译期的访问限制。
1.2 反射的作用
获取类信息 :运行时获取对象所属类的名称、包名、父类、实现的接口等;
动态创建对象 :无需 new 关键字,通过类名字符串构造任意类的对象;
访问成员变量 :获取类的所有变量(包括私有、final 变量),并读写其值;
调用方法 :获取类的所有方法(包括私有方法),并动态调用;
解析注解 :运行时读取类 / 方法 / 属性上的注解,是框架实现注解驱动的核心。
2. Class 类:反射的根源
2.1 Class 类概述
JVM 加载完类后,会在堆内存的方法区中生成一个 Class 类型的对象 —— 这个对象是该类的'说明书',包含了类的所有信息(类名、父类、接口、属性、方法、构造器等)。
核心特点:
每个类在 JVM 中只有一份字节码 ,对应唯一的 Class 对象;
Class 对象是反射的入口,所有反射操作都基于 Class 对象展开;
无论是自定义的 Person 类,还是 JDK 内置的 String/ArrayList,加载后都会生成对应的 Class 对象。
2.2 获取 Class 对象的三种方式(附案例)
获取 Class 对象有三种核心方式,以下以 Student 类为例演示:
第一步:定义 Student 测试类
public class Student {
private String name;
private int age;
private String address;
public Student () {}
private Student (String name) { this .name = name; }
Student(String name, int age) { this .name = name; this .age = age; }
public Student {
.name = name;
.age = age;
.address = address;
}
{
System.out.println( );
}
{
System.out.println( );
}
{
System.out.println( + s);
}
String {
+ s + + i;
}
String {
+ + name + + + age + + address + + ;
}
}
(String name, int age, String address)
this
this
this
private
void
function
()
"执行 function()"
public
void
method1
()
"执行 method1()"
public
void
method2
(String s)
"执行 method2:"
public
method3
(String s, int i)
return
"执行 method3:"
","
@Override
public
toString
()
return
"Student{"
"name='"
'\''
", age="
", address='"
'\''
'}'
第二步:获取 Class 对象的三种方式 public class ClassTest {
public static void main (String[] args) throws ClassNotFoundException {
System.out.println("---------方式 1:类.class---------" );
Class<Student> c1 = Student.class;
System.out.println(c1);
Class<Student> c2 = Student.class;
System.out.println(c1 == c2);
System.out.println("---方式 2:对象.getClass()---" );
Student s = new Student ();
Class<? extends Student > c3 = s.getClass();
System.out.println(c1 == c3);
System.out.println("----方式 3:Class.forName(全类名)----" );
Class<?> c4 = Class.forName("com.hg.java.Student" );
System.out.println(c1 == c4);
}
}
3. Constructor:操作类的构造器
3.1 Constructor 类概述 java.lang.reflect.Constructor 是反射体系中描述类的构造器 的类:
类的每个构造器(无参 / 有参、公有 / 私有)都对应一个 Constructor 对象;
通过 Constructor 对象可在运行时创建类的实例,甚至调用私有构造器。
3.2 获取 Constructor 对象的方法(附案例) 方法 说明 Constructor<?>[] getConstructors()返回所有公共 构造方法的数组 Constructor<?>[] getDeclaredConstructors()返回所有 构造方法的数组(含私有) Constructor getConstructor(Class<?>... parameterTypes)返回单个公共 构造方法(指定参数类型) Constructor getDeclaredConstructor(Class<?>...parameterTypes)返回单个构造方法(含私有,指定参数类型)
案例:获取 Student 类的构造器 public class ConstructorTest {
public static void main (String[] args) throws ClassNotFoundException, NoSuchMethodException {
Class<?> c = Class.forName("com.hg.java1.Student" );
System.out.println("---返回所有构造方法的数组----" );
Constructor<?>[] cons = c.getDeclaredConstructors();
for (Constructor con : cons) {
System.out.println(con);
}
System.out.println("-----返回单个构造方法----" );
Constructor<?> con = c.getConstructor();
System.out.println(con);
con = c.getConstructor(String.class, int .class, String.class);
System.out.println(con);
}
}
3.3 Constructor 常用方法(附案例) 核心方法:T newInstance(Object...initargs) —— 根据指定构造器创建对象。
public class ConstructorTest {
public static void main (String[] args) throws Exception {
Class<?> c = Class.forName("com.hg.java1.Student" );
System.out.println("------通过反射获取公共构造方法并创建对象--------" );
Constructor<?> con = c.getConstructor();
Student s1 = (Student) con.newInstance();
System.out.println(s1);
con = c.getConstructor(String.class, int .class, String.class);
Object obj = con.newInstance("林青霞" , 30 , "西安" );
System.out.println(obj);
}
}
4. Field:操作类的成员变量
4.1 Field 类概述 java.lang.reflect.Field 是反射体系中描述类的成员变量 的类:
每个成员变量(公有 / 私有、静态 / 实例、final)都对应一个 Field 对象;
通过 Field 对象可在运行时读写变量值,突破访问权限限制。
4.2 获取 Field 对象的方法(附案例) 方法 说明 Field[] getFields()返回所有公共 成员变量的数组 Field[] getDeclaredFields()返回所有 成员变量的数组(含私有) Field getField(String name)返回单个公共 成员变量(指定变量名) Field getDeclaredField(String name)返回单个成员变量(含私有,指定变量名)
案例:获取 Student 类的成员变量 public class FieldTest {
public static void main (String[] args) throws Exception {
Class<?> c = Class.forName("com.hg.java1.Student" );
System.out.println("---------返回所有公共成员变量的数组----------" );
Field[] fields = c.getFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("---------返回所有成员变量的数组----------" );
fields = c.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("---------返回单个公共成员变量----------" );
Field addressField = c.getField("address" );
System.out.println(addressField);
System.out.println("---------返回单个私有成员变量----------" );
Field nameField = c.getDeclaredField("name" );
System.out.println(nameField);
}
}
4.3 Field 常用方法(附案例) 核心方法:void set(Object obj,Object value) —— 给指定对象的成员变量赋值。
public class FieldTest {
public static void main (String[] args) throws Exception {
Class<?> c = Class.forName("com.hg.java1.Student" );
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
Field addressField = c.getField("address" );
addressField.set(obj, "西安" );
System.out.println(obj);
Field ageField = c.getDeclaredField("age" );
ageField.setAccessible(true );
ageField.set(obj, 30 );
System.out.println(obj);
}
}
5. Method:操作类的成员方法
5.1 Method 类概述 java.lang.reflect.Method 是反射体系中描述类的成员方法 的类:
每个方法(公有 / 私有、静态 / 实例、有参 / 无参)都对应一个 Method 对象;
通过 Method 对象可在运行时调用方法,包括私有方法。
5.2 获取 Method 对象的方法(附案例) 方法 说明 Method[] getMethods()返回所有公共 成员方法的数组(含父类继承的) Method[] getDeclaredMethods()返回所有 成员方法的数组(仅本类,含私有) Method getMethod(String name, Class<?>... parameterTypes)返回单个公共 方法(指定方法名 + 参数类型) Method getDeclaredMethod(String name, Class<?>... parameterTypes)返回单个方法(含私有,指定方法名 + 参数类型)
案例:获取 Student 类的成员方法 public class MethodTest {
public static void main (String[] args) throws Exception {
Class<?> c = Class.forName("com.hg.java1.Student" );
System.out.println("-----------返回所有公共成员方法的数组--------" );
Method[] methods = c.getMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("-----------返回所有成员方法的数组--------" );
methods = c.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("-----------单个公共成员方法--------" );
Method method = c.getMethod("method1" );
System.out.println(method);
Method method2 = c.getMethod("method2" , String.class);
System.out.println(method2);
Method method3 = c.getMethod("method3" , String.class, int .class);
System.out.println(method3);
System.out.println("-----------单个非公共成员方法--------" );
Method method4 = c.getDeclaredMethod("function" );
System.out.println(method4);
}
}
5.3 Method 常用方法(附案例) 核心方法:Object invoke(Object obj,Object... args) —— 调用指定对象的方法,参数为 args,返回值为方法执行结果。
public class MethodTest {
public static void main (String[] args) throws Exception {
Class<?> c = Class.forName("com.hg.java1.Student" );
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
Method method = c.getMethod("method1" );
method.invoke(obj);
Method method2 = c.getMethod("method2" , String.class);
method2.invoke(obj, "林青霞" );
Method method3 = c.getMethod("method3" , String.class, int .class);
Object o = method3.invoke(obj, "林青霞" , 30 );
System.out.println(o);
Method method4 = c.getDeclaredMethod("function" );
method4.setAccessible(true );
method4.invoke(obj);
}
}
6. Annotation:操作类的注解
6.1 Annotation 类概述 java.lang.annotation.Annotation 是反射体系中描述注解 的类:
每个加在类 / 方法 / 属性上的注解,都对应一个 Annotation 对象;
反射可运行时读取注解的属性值,判断元素是否被注解标记(框架核心用法);
注解必须标注 @Retention(RetentionPolicy.RUNTIME),否则反射无法读取。
6.2 获取 Annotation 对象的方法(附案例) 方法 说明 Annotation[] getAnnotations()返回元素上的所有注解(含继承的) Annotation[] getDeclaredAnnotations()返回元素上的所有注解(仅本元素) Annotation getAnnotation(Class<?> annoClass)返回指定类型的注解(含继承的) Annotation getDeclaredAnnotation(Class<?> annoClass)返回指定类型的注解(仅本元素) isAnnotationPresent(Class<A> annoClass)判断元素是否被指定注解标记
案例:解析类 / 属性 / 方法上的注解 import java.lang.annotation.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.annotation.Annotation;
public class AnnotationTest {
public static void main (String[] args) throws Exception {
Class<?> clazz = Class.forName("com.hg.java1.SampleClass" );
System.out.println("----------解析类上的注解---------" );
if (clazz.isAnnotationPresent(CustomAnnotation.class)) {
CustomAnnotation customAnnotation = clazz.getAnnotation(CustomAnnotation.class);
System.out.println("类注解-name: " + customAnnotation.name());
System.out.println("类注解-value: " + customAnnotation.value());
}
System.out.println("----------解析属性上的注解---------" );
Field field = clazz.getDeclaredField("sampleField" );
if (field.isAnnotationPresent(CustomAnnotation.class)) {
CustomAnnotation customAnnotation = field.getAnnotation(CustomAnnotation.class);
System.out.println("属性注解-name: " + customAnnotation.name());
System.out.println("属性注解-value: " + customAnnotation.value());
}
System.out.println("----------解析方法上的注解---------" );
Method method = clazz.getMethod("getSampleField" );
if (method.isAnnotationPresent(CustomAnnotation.class)) {
CustomAnnotation customAnnotation = method.getAnnotation(CustomAnnotation.class);
System.out.println("方法注解-name: " + customAnnotation.name());
System.out.println("方法注解-value: " + customAnnotation.value());
}
}
}
@Retention(RetentionPolicy.RUNTIME)
@interface CustomAnnotation {
String name () default "这是 name" ;
String value () default "这是 value" ;
}
@CustomAnnotation(name="SampleClass", value = "Sample Class Annotation")
class SampleClass {
@CustomAnnotation(name="sampleField", value = "Sample Field Annotation")
private String sampleField;
@CustomAnnotation(name="getSampleMethod", value = "Sample Method Annotation")
public String getSampleField () {
return sampleField;
}
public void setSampleField (String sampleField) {
this .sampleField = sampleField;
}
}
7. 实战作业(3 道经典反射练习题)
作业 1:通过反射越过泛型检查,给 ArrayList添加字符串 要求:反射突破泛型的编译期检查,往 ArrayList<Integer> 中添加字符串数据。
ArrayList<Integer> intList = new ArrayList <>();
intList.add(100 );
作业 2:通过反射运行配置文件中指定类的指定方法 要求:使用 Properties 解析配置文件,反射调用指定类的指定方法。
public class Student {
public void study () {
System.out.println("好好学习天天向上" );
}
}
className =com.java.exer.Student
methodName =study
作业 3:反射解析注解并动态调用方法
判断 StudentController 类是否添加 @MyController 注解;
若添加,则将标注 @MyRequestMapping 的方法存入 HashMap;
控制台输入方法名,调用对应的方法。
@MyController
public class StudentController {
@MyRequestMapping
public void method1 () {
System.out.println("执行了 method1()" );
}
public void method2 () {
System.out.println("执行了 method2()" );
}
@MyRequestMapping
public void method3 () {
System.out.println("执行了 method3()" );
}
}
@Retention(RetentionPolicy.RUNTIME)
public @interface MyController {
String name () default "这是 name" ;
String value () default "这是 value" ;
}
@Retention(RetentionPolicy.RUNTIME)
public @interface MyRequestMapping {
String name () default "这是 name" ;
String value () default "这是 value" ;
}
总结 反射是 Java 中极具威力的特性,核心是通过 JVM 中的类元数据突破编译期限制,实现动态化编程。掌握 Class、Constructor、Field、Method、Annotation 的使用,是理解 Spring 等框架底层原理的关键。建议结合本文案例动手实践,再完成课后作业,彻底掌握反射的核心用法。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online