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高级编程的核心,常和集合、泛型等数据结构结合使用,掌握它能帮你理解框架的底层逻辑

相关推荐
23471021272 小时前
4.18 学习笔记
软件测试·笔记·python·学习
苏瞳儿5 小时前
java对数据库的增删改查
java·数据库·oracle
zhangjw345 小时前
Java基础语法:变量、数据类型与运算符,从原理到实战
java·开发语言
算法鑫探8 小时前
闰年判断:C语言实战解析
c语言·数据结构·算法·新人首发
yaoxin5211238 小时前
384. Java IO API - Java 文件复制工具:Copy 示例完整解析
java·开发语言·python
Greyson18 小时前
Layui表格如何使用第三方插件实现树形展示.txt
jvm·数据库·python
2401_871696528 小时前
mysql行级锁失效的原因排查_检查查询条件与执行计划
jvm·数据库·python
NotFound4868 小时前
实战指南如何实现Java Web 拦截机制:Filter 与 Interceptor 深度分享
java·开发语言·前端
木子墨5168 小时前
LeetCode 热题 100 精讲 | 并查集篇:最长连续序列 · 岛屿数量 · 省份数量 · 冗余连接 · 等式方程的可满足性
数据结构·c++·算法·leetcode