当前位置: 首页 > news >正文

Java 反射

目录

    • 什么是反射
    • 反射的核心类
      • Class 类
        • 简介
        • 获取 Class 对象
        • 常用方法
      • Constructor 类
        • 简介
        • 常用方法
        • 示例
        • 获取 public 无参构造器
        • 获取 private 有参构造器
        • 获取所有构造器
      • Field 类
        • 简介
        • 获取 Field 对象
        • 常用方法
        • 示例
        • 操作静态字段
      • Method 类
        • 作用
        • 获取 Method 对象的方式
        • 常用方法
        • 示例
      • Modifier 类
        • 作用
        • 常见修饰符
        • 常用方法
        • 示例
      • Array 类
        • 作用
        • 常用方法
        • 使用示例
    • 反射的性能影响
    • 反射的底层实现机制
    • 反射实战
      • 框架实现 IOC 容器
      • 实现 ORM 框架的实体与数据库映射
      • 通用 Bean 属性拷贝工具
      • 动态调用插件类(插件机制、热加载)
      • JDK 动态代理(AOP、事务、日志)
      • 实现通用 JSON 序列化工具
      • 反射操作数组(不确定类型的数组操作)

什么是反射

反射是 Java 提供的一种强大机制,允许在运行时动态获取类的信息、动态创建对象、调用方法、访问字段等

反射的核心类

Class 类

简介

Java 一切类在 JVM 中都是 Class 类的实例

作用:获取类的所有信息(字段、方法、构造器、注解、父类、接口等)

获取 Class 对象
Class<?> clazz = Class.forName("com.example.User");
常用方法
// 获取类的完全限定名(包含包名)
clazz.getName(); 
// 例:com.example.User// 获取类的简单名(不包含包名)
clazz.getSimpleName(); 
// 例:User// 获取类的包名(Java 9 以后推荐用 getPackageName)
clazz.getPackageName(); 
// 例:com.example// 获取类中所有 public 的成员变量(包括继承自父类的 public 成员)
clazz.getFields(); // 获取类中声明的所有成员变量(不论权限,private、protected、public、default),但不包括继承自父类的
clazz.getDeclaredFields();// 获取类中所有 public 的方法(包括继承自父类的 public 方法)
clazz.getMethods(); // 获取类中声明的所有方法(不论权限,private、protected、public、default),但不包括继承的
clazz.getDeclaredMethods(); // 获取类中所有 public 的构造方法
clazz.getConstructors(); // 获取类的直接父类(如果没有则返回 null,像 Object)
clazz.getSuperclass(); // 获取类实现的所有接口(不包括父类实现的接口)
clazz.getInterfaces(); 

Constructor 类

简介
  • 代表类的构造方法
  • 用于获取、操作类的构造器,动态创建实例
  • 即使构造器是私有的,也可以通过反射访问
常用方法
方法说明
getConstructor(参数类型...)获取 public构造器
getDeclaredConstructor(参数类型...)获取指定参数的构造器(包括 private
getConstructors()获取所有 public构造器
getDeclaredConstructors()获取所有构造器(包括 private
示例
class User {private String name;private int age;// 无参构造public User() {this.name = "默认名";}// 有参构造private User(String name, int age) {this.name = name;this.age = age;}public void show() {System.out.println("User{name='" + name + "', age=" + age + "}");}
}
获取 public 无参构造器
Class<User> clazz = User.class;
Constructor<User> constructor = clazz.getConstructor();
User user = constructor.newInstance();
user.show();
获取 private 有参构造器
Constructor<User> privateConstructor = clazz.getDeclaredConstructor(String.class, int.class);
privateConstructor.setAccessible(true);
User user2 = privateConstructor.newInstance("张三", 20);
user2.show();
获取所有构造器
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> cons : constructors) {System.out.println(cons);
}

Field 类

简介
  • 用于表示并操作类的成员变量(包括 publicprivateprotectedstatic 等)
  • 支持对字段进行 动态获取、读取、修改、访问控制破坏
获取 Field 对象
方法说明
getField(String name)获取 public字段
getDeclaredField(String name)获取任意字段(包括 privateprotected
getFields()获取所有 public字段
getDeclaredFields()获取所有字段(包括 privateprotected
常用方法
方法说明
get(Object obj)获取字段值
set(Object obj, Object value)设置字段值
getType()获取字段类型
getModifiers()获取字段修饰符
setAccessible(true)破坏封装,允许访问 private字段
getName()获取字段名
isAnnotationPresent()判断字段上是否有某个注解
示例
class User {public String username;private int age;@Deprecatedprivate String secret = "秘密";
}

获取并操作public字段

Class<User> clazz = User.class;
Field field = clazz.getField("username");User user = new User();
field.set(user, "张三");
String value = (String) field.get(user);System.out.println("用户名: " + value);

获取并操作private字段

Field privateField = clazz.getDeclaredField("age");
privateField.setAccessible(true);  // 破坏封装
privateField.set(user, 20);
int age = (int) privateField.get(user);System.out.println("年龄: " + age);

获取字段信息

Field field = clazz.getDeclaredField("secret");
System.out.println("字段名: " + field.getName());
System.out.println("字段类型: " + field.getType());
System.out.println("修饰符: " + Modifier.toString(field.getModifiers()));

判断注解

if (field.isAnnotationPresent(Deprecated.class)) {System.out.println("该字段已被标记为 Deprecated");
}
操作静态字段
Field staticField = MyClass.class.getDeclaredField("STATIC_FIELD");
staticField.setAccessible(true);
staticField.set(null, "新值");  // 静态字段 obj 传 null

Method 类

作用

Methodjava.lang.reflect 包中的类

表示类中的一个成员方法(实例方法、静态方法)

可以通过 Method 类动态调用对象的方法,即使是私有方法

获取 Method 对象的方式
方法说明
getMethod(String name, Class<?>... parameterTypes)获取 public方法(包括父类方法)
getDeclaredMethod(String name, Class<?>... parameterTypes)获取当前类声明的方法(包括 private
getMethods()获取所有 public方法(包括继承自父类)
getDeclaredMethods()获取当前类声明的所有方法(包括 private
常用方法
方法说明
invoke(Object obj, Object... args)调用该方法
getName()获取方法名
getReturnType()获取返回类型
getParameterTypes()获取参数类型数组
getModifiers()获取方法修饰符
setAccessible(true)破坏封装,允许访问 private
方法
isAnnotationPresent()判断方法上是否存在指定注解
示例
class User {public void sayHello(String name) {System.out.println("Hello, " + name);}private int add(int a, int b) {return a + b;}
}

获取并调用 public 方法

Class<User> clazz = User.class;
Method method = clazz.getMethod("sayHello", String.class);User user = new User();
method.invoke(user, "张三");

获取并调用 private 方法

Method privateMethod = clazz.getDeclaredMethod("add", int.class, int.class);
privateMethod.setAccessible(true);
int result = (int) privateMethod.invoke(user, 5, 3);System.out.println("加法结果: " + result);

获取方法信息

Method method = clazz.getDeclaredMethod("add", int.class, int.class);
System.out.println("方法名: " + method.getName());
System.out.println("返回类型: " + method.getReturnType());
System.out.println("参数类型: " + Arrays.toString(method.getParameterTypes()));
System.out.println("修饰符: " + Modifier.toString(method.getModifiers()));

判断注解

if (method.isAnnotationPresent(Deprecated.class)) {System.out.println("该方法已过时");
}

Modifier 类

作用

位于 java.lang.reflect 包。

用于解析类、方法、字段、构造器等的访问修饰符(例如 publicprivatestaticfinalabstract 等)。

通过该类可以将修饰符的 int 值转换为可读的字符串,并进行修饰符检查。

常见修饰符
常量十进制值说明
Modifier.PUBLIC1public
Modifier.PRIVATE2private
Modifier.PROTECTED4protected
Modifier.STATIC8static
Modifier.FINAL16final
Modifier.SYNCHRONIZED32synchronized
Modifier.VOLATILE64volatile
Modifier.TRANSIENT128transient
Modifier.ABSTRACT1024abstract
Modifier.INTERFACE512interface
Modifier.NATIVE256native
常用方法
方法说明
toString(int mod)将修饰符 int 值转为字符串
isPublic(int mod)判断是否是 public
isPrivate(int mod)判断是否是 private
isProtected(int mod)判断是否是 protected
isStatic(int mod)判断是否是 static
isFinal(int mod)判断是否是 final
isAbstract(int mod)判断是否是 abstract
isSynchronized(int mod)判断是否是 synchronized
isNative(int mod)判断是否是 native
isVolatile(int mod)判断是否是 volatile
isTransient(int mod)判断是否是 transient
isInterface(int mod)判断是否是接口
示例
public class User {private static final String NAME = "张三";public void sayHello() {}
}

示例代码

Class<User> clazz = User.class;// 获取字段修饰符
Field field = clazz.getDeclaredField("NAME");
int fieldModifiers = field.getModifiers();
System.out.println("字段修饰符: " + Modifier.toString(fieldModifiers));
System.out.println("是否是 static: " + Modifier.isStatic(fieldModifiers));
System.out.println("是否是 final: " + Modifier.isFinal(fieldModifiers));// 获取方法修饰符
Method method = clazz.getMethod("sayHello");
int methodModifiers = method.getModifiers();
System.out.println("方法修饰符: " + Modifier.toString(methodModifiers));
System.out.println("是否是 public: " + Modifier.isPublic(methodModifiers));

输出

字段修饰符: private static final
是否是 static: true
是否是 final: true
方法修饰符: public
是否是 public: true

Array 类

作用
  • 提供在运行时动态创建、访问、修改数组的方法
  • 支持任意类型、任意维度的数组操作
  • 解决反射场景下无法直接操作数组的问题
常用方法
方法说明
newInstance(Class<?> componentType, int length)创建一维数组
newInstance(Class<?> componentType, int... dimensions)创建多维数组
get(Object array, int index)获取数组中的元素
set(Object array, int index, Object value)设置数组中的元素
getLength(Object array)获取数组长度
使用示例

动态创建一维数组

int[] intArray = (int[]) Array.newInstance(int.class, 5);Array.set(intArray, 0, 10);
Array.set(intArray, 1, 20);System.out.println(Array.get(intArray, 0));  // 10
System.out.println(Array.get(intArray, 1));  // 20
System.out.println("数组长度: " + Array.getLength(intArray));  // 5

动态创建多维数组

int[][] matrix = (int[][]) Array.newInstance(int.class, 3, 3);Array.set(Array.get(matrix, 0), 0, 100);
System.out.println(((int[]) Array.get(matrix, 0))[0]);  // 100

获取数组信息

String[] strs = new String[]{"A", "B", "C"};
System.out.println("数组类型: " + strs.getClass().getName());
System.out.println("数组长度: " + Array.getLength(strs));

反射的性能影响

  • 反射比直接调用慢(通常慢 10-20 倍),但合理使用影响可以接受
  • 使用缓存可以降低反射带来的性能损耗
  • MethodHandleLambdaMetafactory 可替代部分反射,性能更优

反射的底层实现机制

  • 反射通过 JVM 提供的元数据实现(类的元信息、方法表、字段表)
  • 访问字段、方法底层通过 Unsafe、JNI 实现直接操作内存
  • Class 类是所有类的元数据载体

反射实战

框架实现 IOC 容器

  • 反射用于根据配置或注解,动态创建对象并注入到容器

示例:

public class BeanFactory {public static Object createBean(String className) throws Exception {Class<?> clazz = Class.forName(className);return clazz.getDeclaredConstructor().newInstance();}public static void main(String[] args) throws Exception {Object obj = createBean("java.util.ArrayList");System.out.println(obj.getClass().getName()); // java.util.ArrayList}
}

实现 ORM 框架的实体与数据库映射

  • 反射读取实体类字段,自动生成 SQL 语句,自动赋值

示例

public static void printInsertSQL(Object obj) throws Exception {Class<?> clazz = obj.getClass();StringBuilder sb = new StringBuilder("INSERT INTO ");sb.append(clazz.getSimpleName()).append(" VALUES(");Field[] fields = clazz.getDeclaredFields();for (Field field : fields) {field.setAccessible(true);sb.append("'").append(field.get(obj)).append("', ");}sb.setLength(sb.length() - 2); // 移除最后的逗号sb.append(")");System.out.println(sb);
}class User {private String name = "张三";private int age = 20;
}printInsertSQL(new User());
// INSERT INTO User VALUES('张三', '20')

通用 Bean 属性拷贝工具

  • 反射实现对象属性值的动态拷贝

示例

public static void copyProperties(Object source, Object target) throws Exception {Class<?> clazz = source.getClass();for (Field field : clazz.getDeclaredFields()) {field.setAccessible(true);Object value = field.get(source);field.set(target, value);}
}class Person {private String name = "李四";private int age = 30;
}Person p1 = new Person();
Person p2 = new Person();
copyProperties(p1, p2);

动态调用插件类(插件机制、热加载)

  • 反射动态加载指定类并调用其方法,不需要预编译绑定

示例:

public static void executePlugin(String className, String methodName) throws Exception {Class<?> clazz = Class.forName(className);Object obj = clazz.getDeclaredConstructor().newInstance();Method method = clazz.getDeclaredMethod(methodName);method.invoke(obj);
}class MyPlugin {public void run() {System.out.println("插件启动");}
}executePlugin("MyPlugin", "run");
// 插件启动

JDK 动态代理(AOP、事务、日志)

  • 反射是动态代理的基础,动态创建代理对象

示例(简化版):

import java.lang.reflect.*;interface Service {void doSomething();
}class ServiceImpl implements Service {public void doSomething() {System.out.println("执行业务逻辑");}
}Service proxy = (Service) Proxy.newProxyInstance(ServiceImpl.class.getClassLoader(),new Class[]{Service.class},(proxyObj, method, args1) -> {System.out.println("开始事务");Object result = method.invoke(new ServiceImpl(), args1);System.out.println("提交事务");return result;}
);proxy.doSomething();
// 开始事务
// 执行业务逻辑
// 提交事务

实现通用 JSON 序列化工具

  • 反射获取字段并转成 JSON

示例:

public static String toJson(Object obj) throws Exception {Class<?> clazz = obj.getClass();StringBuilder sb = new StringBuilder("{");for (Field field : clazz.getDeclaredFields()) {field.setAccessible(true);sb.append("\"").append(field.getName()).append("\":\"").append(field.get(obj)).append("\",");}sb.setLength(sb.length() - 1);sb.append("}");return sb.toString();
}class Book {private String title = "Java核心技术";private double price = 99.9;
}System.out.println(toJson(new Book()));
// {"title":"Java核心技术","price":"99.9"}

反射操作数组(不确定类型的数组操作)

  • 例如构建任意类型、任意长度的数组

示例:

Object array = Array.newInstance(String.class, 5);
Array.set(array, 0, "Hello");
System.out.println(Array.get(array, 0)); // Hello
http://www.xdnf.cn/news/435763.html

相关文章:

  • 久坐办公自动提醒休息的工具
  • QLineEdit增加点击回显功能
  • PH热榜 | 2025-05-13
  • arctanx 导数 泰勒展开式证明
  • 机器学习2
  • 鹅厂面试数学题
  • 典籍指数问答模块回答格式修改
  • java中的Optional
  • 如何优化 Linux 服务器的磁盘 I/O 性能
  • 【Nova UI】十五、打造组件库之滚动条组件(上):滚动条组件的起步与进阶
  • 【学习笔记】Shell编程---流程控制语句
  • PNG图片转icon图标Python脚本(简易版) - 随笔
  • 动态规划问题 -- 多状态模型(打家劫舍)
  • Java的进制转换
  • 大模型驱动的写实数字人实时对话:创新与实践
  • 谈谈各种IO模型
  • 算法·KMP
  • 1688 API 接口使用限制
  • 【C++】多线程和多进程
  • Java Spring 事件驱动机制
  • 中医诊所药房开处方调剂库存管理h5/pc开源版开发
  • 提供全球86国/地区进出口税费,46国/地区监管条件,53国/地区税费计算
  • 第二十三天打卡
  • 项目管理系统流程:高效运作的关键所在
  • 使用ADB命令操作Android的apk/aab包
  • [SAP] 通过程序名获取事务码TCode
  • Python实例题:Pvthon实现简单的Web服务器
  • AI 编程新时代!字节 Seed-Coder 重磅登场
  • 第六章QT基础: Lambda表达式补充
  • [250513] “End of 10” 活动:应对 Windows 10 支持终止,推广 Linux 转型