java数据结构当中的《反射》

一、反射是什么?(通俗理解)

反射是Java提供的一种机制,允许程序在运行时(而不是编译时):

1.获取任意类的完整信息(类名、属性、方法、构造器、继承关系等)

2.操作任意对象的属性和方法(即使是private修饰的)

3.动态创建对象、调用方法,无需提前知道类的具体名称

定义
Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法 ;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制

可以把反射理解为:程序自己 "审视" 和 "操作" 自己的能力。就像一个人能看清自己的身体结构,还能手动控制自己的器官运作。

反射最重要的用途就是开发各种通用框架

二、反射的核心类(都在java.lang.reflect包下)

三、反射的基本使用步骤(实战示例)

先定义一个普通的测试类,后续用反射操作它:

java 复制代码
public class Student {
    // 私有属性
    private String name;
    // 公有属性
    public int age;
    
    // 无参构造
    public Student() {}
    
    // 有参构造
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    // 私有方法
    private String sayHello(String msg) {
        return name + "说:" + msg;
    }
    
    // 公有方法
    public void showInfo() {
        System.out.println("姓名:" + name + ",年龄:" + age);
    }

    // getter/setter(省略,后面会用反射操作name)
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
}

步骤 1:获取 Class 对象(反射的入口)

获取Class对象有 3 种方式:

java 复制代码
public class ReflectionDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // 方式1:通过类名.class(编译时已知类)
        Class<Student> clazz1 = Student.class;
        
        // 方式2:通过对象.getClass()(已有对象)
        Student student = new Student();
        Class<? extends Student> clazz2 = student.getClass();
        
        // 方式3:通过Class.forName("全类名")(运行时动态获取,最灵活)
        Class<?> clazz3 = Class.forName("com.example.Student");
        
        // 验证:三个Class对象是同一个(JVM中每个类只有一个Class实例)
        System.out.println(clazz1 == clazz2); // true
        System.out.println(clazz1 == clazz3); // true
    }
}

步骤 2:通过反射创建对象

java 复制代码
// 1. 调用无参构造创建对象
Class<?> clazz = Class.forName("com.example.Student");
Student s1 = (Student) clazz.newInstance(); // 旧方式(JDK9后标记为过时)
// 推荐方式:通过Constructor调用无参构造
Constructor<?> constructor = clazz.getConstructor();
Student s1 = (Student) constructor.newInstance();

// 2. 调用有参构造创建对象
Constructor<?> constructor2 = clazz.getConstructor(String.class, int.class);
Student s2 = (Student) constructor2.newInstance("张三", 18);
s2.showInfo(); // 输出:姓名:张三,年龄:18

步骤 3:通过反射操作属性(包括私有属性)

java 复制代码
// 1. 获取并修改公有属性age
Field ageField = clazz.getField("age");
ageField.set(s2, 20); // 给s2的age赋值20
System.out.println(ageField.get(s2)); // 输出20

// 2. 获取并修改私有属性name(需要先设置可访问)
Field nameField = clazz.getDeclaredField("name"); // getDeclaredField能获取所有修饰符的属性
nameField.setAccessible(true); // 关闭访问检查(突破private限制)
nameField.set(s2, "李四");
System.out.println(nameField.get(s2)); // 输出李四

步骤 4:通过反射调用方法(包括私有方法)

java 复制代码
// 1. 调用公有方法showInfo
Method showInfoMethod = clazz.getMethod("showInfo");
showInfoMethod.invoke(s2); // 输出:姓名:李四,年龄:20

// 2. 调用私有方法sayHello
Method sayHelloMethod = clazz.getDeclaredMethod("sayHello", String.class);
sayHelloMethod.setAccessible(true); // 关闭访问检查
String result = (String) sayHelloMethod.invoke(s2, "你好!");
System.out.println(result); // 输出:李四说:你好!

四、反射的应用场景

  1. 框架核心:Spring、MyBatis、Hibernate等框架大量使用反射(比如 Spring的IOC容器动态创建 Bean,MyBatis的结果集映射)。
  2. 动态代理:AOP(面向切面编程)的底层实现依赖反射。
  3. 工具类:比如JSON序列化/反序列化工具(FastJSON、Jackson),通过反射读取对象属性并转为JSON。
  4. 插件/扩展开发:运行时动态加载外部类并调用其方法。

五、反射的优缺点


总结

1.核心本质 :反射是Java程序在运行时获取类信息、操作对象的机制,核心入口是c1ass类。

2.关键操作 :获取class对象→创建对象→操作属性/方法(私有成员需设置setAccessible(true))。

3.核心价值:是框架的基础,实现"动态编程",但日常开发中应尽量少用(避免性能和封装性问题)。

反射本身不属于"数据结构",但它是Java高级编程的核心,常和集合、泛型等数据结构结合使用,掌握它能帮你理解框架的底层逻辑

相关推荐
YJlio8 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
l1t8 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
青云计划8 小时前
知光项目知文发布模块
java·后端·spring·mybatis
赶路人儿8 小时前
Jsoniter(java版本)使用介绍
java·开发语言
2013编程爱好者8 小时前
【C++】树的基础
数据结构·二叉树··二叉树的遍历
NEXT068 小时前
二叉搜索树(BST)
前端·数据结构·面试
化学在逃硬闯CS9 小时前
Leetcode1382. 将二叉搜索树变平衡
数据结构·算法
山塘小鱼儿9 小时前
本地Ollama+Agent+LangGraph+LangSmith运行
python·langchain·ollama·langgraph·langsimth
探路者继续奋斗9 小时前
IDD意图驱动开发之意图规格说明书
java·规格说明书·开发规范·意图驱动开发·idd