Java反射机制基础入门

文章目录

反射是Java重要的基础特性,也是Spring、MyBatis等主流框架的底层核心支撑。本文聚焦反射基础知识,让读者快速掌握反射核心概念与基础使用方法。


一、反射机制概述

常规对象操作方式

在日常Java开发中,绝大多数代码都属于静态编码。程序在编译阶段就确定好需要使用的类、成员方法与成员变量,通过new关键字直接创建对象并完成业务调用,整个流程固定且可控。

java 复制代码
// 编译阶段确定调用类与方法
User user = new User();
user.setName("张三");
反射的基本概念

反射是Java提供的动态编程机制,核心特性为:程序在运行阶段,可以动态获取目标类的结构信息、创建类实例、操作成员变量以及调用类中的方法。

两种编码方式核心区别:

  • 常规正向操作:提前明确类结构,直接调用类的功能
  • 反射动态操作:运行时解析类结构,动态完成功能调用
反射的核心原理

当JVM加载一个Java类时,会自动生成一个唯一的Class类对象,该对象完整封装了当前类的所有结构信息,包含构造方法、成员变量、成员方法等。所有反射操作都依托Class对象完成,Class对象是反射机制的唯一入口。


二、Class对象的三种获取方式

反射操作的前提是获取目标类的Class对象,Java提供三种基础获取方式,适配不同的开发场景。

类名.class

通过"类名.class"的方式静态获取Class对象,在编译阶段即可确定,执行效率最高,是静态编码场景的首选方式。

java 复制代码
Class<User> clazz = User.class;
Class<String> stringClazz = String.class;
对象.getClass()

基于已实例化的对象获取Class对象,适用于已经创建对象实例的运行时场景。

java 复制代码
User user = new User();
Class<? extends User> clazz = user.getClass();
Class.forName()

通过传入类的全限定名(包名+类名)字符串动态加载类,可在运行时灵活指定目标类,是框架底层动态加载类的常用方式。

java 复制代码
// 需要填写目标类的完整包名与类名
Class<?> clazz = Class.forName("com.example.User");

三种方式适用场景总结

  • 类名.class:静态获取、性能优异,适用于已知目标类的常规开发场景
  • 对象.getClass():适用于已有对象实例,需要反向获取类信息的场景
  • Class.forName():支持动态配置类路径,多用于框架配置、动态加载场景

三、反射基础实战案例

定义一个基础的User实体类,包含公有、私有成员变量与成员方法,作为反射操作的测试载体。

java 复制代码
public class User {
    // 公有成员变量
    public String username;
    // 私有成员变量
    private Integer age;

    // 无参构造方法
    public User() {}

    // 有参构造方法
    public User(String username, Integer age) {
        this.username = username;
        this.age = age;
    }

    // 普通公有方法
    public void sayHello() {
        System.out.println("反射基础测试成功!");
    }

    // 私有方法
    private void showAge() {
        System.out.println("年龄:" + age);
    }

    // getter、setter方法
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}
反射创建类实例

通过反射调用类的构造方法,可动态创建对象实例,支持无参构造和有参构造两种创建方式。

java 复制代码
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        // 1. 获取目标类的Class对象
        Class<User> clazz = User.class;

        // 2. 通过无参构造创建对象
        User user1 = clazz.getDeclaredConstructor().newInstance();

        // 3. 通过有参构造创建对象
        User user2 = clazz.getDeclaredConstructor(String.class, Integer.class)
                .newInstance("小明", 18);
    }
}
反射操作成员变量

利用反射可以读取和修改对象的成员变量,包含私有成员变量,核心方法用途区分如下:

  • getField():仅获取类的公有成员变量
  • getDeclaredField():获取类中所有权限的成员变量,包含私有变量
  • setAccessible(true):解除私有成员的访问权限限制
java 复制代码
public class ReflectFieldTest {
    public static void main(String[] args) throws Exception {
        Class<User> clazz = User.class;
        User user = clazz.getDeclaredConstructor().newInstance();

        // 操作公有成员属性
        clazz.getField("username").set(user, "小红");
        System.out.println("用户名:" + clazz.getField("username").get(user));

        // 操作私有成员属性
        clazz.getDeclaredField("age").setAccessible(true);
        clazz.getDeclaredField("age").set(user, 20);
        System.out.println("年龄:" + clazz.getDeclaredField("age").get(user));
    }
}
反射调用成员方法

通过反射可以动态调用类的公有方法与私有方法,核心方法用途区分如下:

  • getMethod():获取类的公有成员方法
  • getDeclaredMethod():获取类中所有权限的成员方法,包含私有方法
  • invoke():执行获取到的成员方法
java 复制代码
public class ReflectMethodTest {
    public static void main(String[] args) throws Exception {
        Class<User> clazz = User.class;
        User user = clazz.getDeclaredConstructor().newInstance();

        // 调用公有成员方法
        clazz.getDeclaredMethod("sayHello").invoke(user);

        // 调用私有成员方法
        clazz.getDeclaredMethod("showAge").setAccessible(true);
        clazz.getDeclaredMethod("showAge").invoke(user);
    }
}

四、反射机制的优缺点

  • 优点
    • 灵活性较强:可在程序运行阶段动态解析类结构、操作类成员,突破编译阶段的代码固定限制
    • 框架核心基础:是Spring、MyBatis等主流开源框架的底层实现核心,支撑框架的动态加载、属性注入等功能
  • 缺点
    • 运行性能较低:反射需要动态解析类结构、校验访问权限,相比直接调用代码,执行效率更低
    • 破坏封装特性:可强制访问类的私有成员,打破面向对象的封装原则,存在一定的代码安全隐患

五、总结

  1. 反射的核心原理:依托Class对象,在程序运行时动态解析并操作类的全部资源;
  2. Class对象包含三种获取方式,静态开发优先使用类名.class方式,性能更优;
  3. 反射常用基础功能包含动态创建对象、操作成员变量、调用成员方法,访问私有成员需手动开启权限;
  4. 反射灵活性高但存在性能与封装性短板,常规业务开发不建议滥用,掌握基础用法即可满足日常开发与学习需求。
相关推荐
500844 小时前
HCCL 集合通信编程:多卡协同的正确姿势
java·flutter·性能优化·electron·wpf
霍霍的袁4 小时前
【C++初阶】函数重载详细讲解
开发语言·c++·算法
threelab4 小时前
Three.js 黑洞引力效果着色器 | 三维可视化 / AI 提示词
开发语言·javascript·着色器
陌路204 小时前
详解C++ 高性能网络库 muduo 的精简日志模块
开发语言·c++·php
asdfg12589635 小时前
Java中的Comparator 和JS中的回调函数好相似
java·开发语言
lly2024065 小时前
Python SMTP邮件发送教程
开发语言
会编程的土豆5 小时前
消息队列(MQ)入门笔记
java·笔记·spring
我是伪码农5 小时前
小程序100-125
开发语言·小程序·php
专注VB编程开发20年5 小时前
python运行提速方案全解
java·linux·服务器