深入理解Java反射技术及其应用

news2024/9/23 21:31:58

image-20240909151040278

什么是反射技术?

Java反射机制是一种强大的特性,它允许程序在运行时动态加载类并获取类或对象的属性和方法。其核心在于JVM通过获得class对象进行反编译,从而获取对象的各种信息。

反射机制的基本特点

  1. 动态性
    Java是一种先编译后运行的语言,程序中对象的类型在编译期确定。而反射机制使得在运行时可以动态创建对象和调用其属性,无需在编译期知晓具体运行的对象。

  2. 灵活性
    通过反射,程序可以在运行时动态获取类的成员方法、属性等信息,并对其灵活调用。这一特性使得可以编写更加通用和灵活的代码。

  3. 类加载
    类加载器负责将class文件读取到内存中,反射机制能够在加载类之后,利用class对象访问类的信息。

获取class对象的三种方式

// 1. 通过类名称直接获取
Class<UserEntity> userEntityClass = UserEntity.class;

// 2. 通过实例对象获取
UserEntity userEntity = new UserEntity();
Class<? extends UserEntity> aClass = userEntity.getClass();

// 3. 通过类的完整路径获取
Class<?> aClass1 = Class.forName("com.yk.entity.UserEntity");

反射技术的优缺点

优点:

  • 动态获取:允许在运行时获取类的各种信息,对Java这类编译语言来说,能够更加灵活地创建和使用对象。
  • 无缝集成:能够实现组件之间的动态装配,无需源代码的连接,更容易实现面向对象编程。

缺点:

  • 性能消耗:反射的操作相较于直接调用会消耗更多的系统资源,因此在不需要动态创建对象的情况下最好避免使用反射。
  • 安全隐患:反射机制可以忽略权限检查,可能破坏封装性,导致安全问题。

反射机制的应用场景

  1. JDBC中使用Class.forName("com.yk.jdbc.Driver")
  2. Spring框架底层基于反射初始化对象
  3. 动态代理模式的实现

反射技术示例

1. 使用反射初始化对象

Class<?> aClass = Class.forName("com.yk.entity.UserEntity");
// 创建对象,默认调用无参构造方法
UserEntity userEntity = (UserEntity) aClass.newInstance();
System.out.println(userEntity);

// 使用有参构造方法创建对象
Constructor<?> constructor = aClass.getConstructor(String.class, Integer.class);
UserEntity user = (UserEntity) constructor.newInstance("yk", 21);
System.out.println(user);

2. 获取构造方法

Class<?> aClass = Class.forName("com.yk.entity.UserEntity");
Constructor<?>[] constructors = aClass.getConstructors();  // 获取公有构造方法
for (Constructor<?> co : constructors) {
    System.out.println(co);
}

System.out.println("=======");

Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors(); // 获取所有构造方法
for (Constructor<?> co : declaredConstructors) {
    System.out.println(co);
}

3. 获取成员属性

Field[] fields = aClass.getFields(); // 获取所有公有字段
Field[] declaredFields = aClass.getDeclaredFields(); // 获取所有字段

4. 调用方法

Method nameMethod = aClass.getMethod("setName", String.class);
Method sumMethod = aClass.getMethod("setSum", int.class);

nameMethod.invoke(document, "解忧杂货店");
sumMethod.invoke(document, 30);
System.out.println(document);

5. 模拟MyBatis实现代理

SQL执行器
public class SQLHandler {
    private static final String URL = "jdbc:mysql://127.0.0.1:3306/study?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "root";

    // 执行SQL
    public static <T> List<T> execute(String sql, Class<T> resultType) {
        try (Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
             PreparedStatement preparedStatement = connection.prepareStatement(sql);
             ResultSet resultSet = preparedStatement.executeQuery()) {
             
            ResultSetMetaData setMetaData = resultSet.getMetaData();
            List<T> list = new ArrayList<>();
            while (resultSet.next()) {
                Object resultData = resultType.getDeclaredConstructor().newInstance();
                for (int i = 1; i <= setMetaData.getColumnCount(); i++) {
                    String labelName = setMetaData.getColumnLabel(i);
                    Field declaredField = resultType.getDeclaredField(labelName);
                    declaredField.setAccessible(true);

                    switch (setMetaData.getColumnType(i)) {
                        case Types.INTEGER:
                            declaredField.setInt(resultData, resultSet.getInt(labelName));
                            break;
                        case Types.DOUBLE:
                            declaredField.setDouble(resultData, resultSet.getDouble(labelName));
                            break;
                        default:
                            String value = resultSet.getString(labelName);
                            if ("true".equals(value) || "false".equals(value)) {
                                declaredField.setBoolean(resultData, Boolean.valueOf(value));
                            } else {
                                declaredField.set(resultData, value);
                            }
                    }
                }
                list.add((T) resultData);
            }
            return list;
        } catch (SQLException | InstantiationException | IllegalAccessException | NoSuchFieldException | NoSuchMethodException e) {
            e.printStackTrace();
            return Collections.emptyList();
        }
    }
}
配置SQL语句
sql = select id, city_name_pinyin as cityNamePinyin, city_name as

测试调用

public class Test {
    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        InputStream inputStream = Test.class.getResourceAsStream("sql.properties");
        properties.load(inputStream);
        String sql = properties.getProperty("sql");
        System.out.println(sql);
        List<City> cities = SQLHandler.execute(sql, City.class);
//        System.out.println(cities.size());
        for (City c : cities) {
            System.out.println(c);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2126770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【电子通识】规格书上的%FS和%RD具体指什么?

在仪器仪表类的手册上&#xff0c;常见的精度表达规格显示方式&#xff1a;%FS 和%RD 究竟如何解读呢&#xff1f; 术语解说 %RD(Reading)&#xff1a;用于表示对比显示值(读值)存在多少(%)的误差 %FS(Full Scale)&#xff1a;用于表示对比全量程存在多少(%)的误差 %SP(Set Poi…

基于vue框架的城市体育运动交流平台15s43(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;用户,赛事类型,近期赛事,比赛报名,器材类型,器材信息,自由约战,运动队伍 开题报告内容 基于Vue框架的城市体育运动交流平台开题报告 一、项目背景与意义 随着城市化进程的加速和居民健康意识的提升&#xff0c;城市体育运动已成为现代…

思维导图神器!四款高效工具助你职场逆袭

在如今这个信息爆炸的时代&#xff0c;如何高效地整理和呈现思维&#xff0c;成为了一个重要的能力&#xff1b;思维导图作为一种有效的思维工具&#xff0c;被广泛应用于工作、学习和生活中&#xff1b;今天&#xff0c;我将为大家介绍四款常用的思维导图软件并分享一下它们的…

win10任务栏透明如何调整?——详解Windows任务栏设置与优化技巧

在这个数字化时代&#xff0c;电脑已经成为我们日常办公和生活中的。关于win10任务栏透明的设置方法&#xff0c;身边很多同事都在咨询。 本文就来简单介绍下关于电脑任务栏个性化设置的方法&#xff0c;毕竟任务栏影响着用户体验。这时&#xff0c;一款优秀的任务栏优化工具就…

模拟实现string类: clear函数、流提取(<<)和流插入(>>)运算符重载、>、<、==、<=、>=、!=的运算符重载、赋值运算符(=)重载等的介绍

文章目录 前言一、 clear函数二、流提取(<<)和流插入(>>)运算符重载三、 >、<、、<、>、!的运算符重载四、赋值运算符&#xff08;&#xff09;重载总结 前言 模拟实现string类: clear函数、流提取(<<)和流插入(>>)运算符重载、>、<…

[论文笔记]ChatQA: Surpassing GPT-4 on Conversational QA and RAG

引言 今天来看一下上篇论文笔记中反复介绍的 ChatQA: Surpassing GPT-4 on Conversational QA and RAG。 为了简单&#xff0c;下文中以翻译的口吻记录&#xff0c;比如替换"作者"为"我们"。 我们介绍了 ChatQA&#xff0c;这是一个模型套件&#xff0c;一…

机器学习和深度学习的常见概念总结(面试用,多原创图和公式)

目录 使用说明一、未分类损失函数&#xff08;Loss Function&#xff09;1. **损失函数的作用**2. **常见的损失函数**2.1. **均方误差&#xff08;MSE, Mean Squared Error&#xff09;**2.2. **均方根误差&#xff08;RMSE, Root Mean Squared Error&#xff09;**2.3. **平均…

1. 运动控制指令概要(omron 机器自动化控制器)

机器自动化控制器——第一章 运动控制指令概要 1-1 运动控制指令PLCopen运动控制用功能块运动控制指令概要▶ 运动控制指令的种类▶ 状态变化▶ 运动控制指令的启动和状态▶ 异常处理▶ 执行运动控制指令时输入变量的变更(指令重启)▶ 通过选择缓存模式执行指令多重启动▶ 通过…

四川锦程消费金融有限责任公司2024年(第一批次)催收机构选型入库采购公告

四川锦程消费金融有限责任公司2024年&#xff08;第一批次&#xff09;催收机构选型入库采购公告 根据需要&#xff0c; 四川锦程消费金融有限责任公司决定对外公 开选型采购催收代理合作的催收机构&#xff0c;欢迎符合条件的催收 机构参与采购。具体公告如下&#xff1a; 一…

Redisson分布式锁实现及原理详解

随着技术快速发展&#xff0c;数据规模增大&#xff0c;分布式系统越来越普及&#xff0c;一个应用往往会部署在多台机器上&#xff08;多节点&#xff09;&#xff0c;在有些场景中&#xff0c;为了保证数据不重复&#xff0c;要求在同一时刻&#xff0c;同一任务只在一个节点…

Makefile中的override

若对变量进行赋值一部分需要由命令行&#xff08;注意命令行只能使用/:/进行赋值&#xff0c;不能使用&#xff1f;进行赋值&#xff09;输入完成&#xff0c;一部分需要写在Makefile文件里&#xff0c;Makefile规则默认会让命令行的赋值覆盖文件里的赋值。要想解决这个问题&am…

【源码+文档+调试讲解】高校研招信息共享系统

摘 要 近年来&#xff0c;科技飞速发展&#xff0c;在经济全球化的背景之下&#xff0c;互联网技术将进一步提高社会综合发展的效率和速度&#xff0c;互联网技术也会涉及到各个领域&#xff0c;而高校研招信息共享系统在网络背景下有着无法忽视的作用。信息管理系统的开发是…

log4j靶场,反弹shell

1.用vulhub靶场搭建&#xff0c;首先进入目录CVE-2021-44228中&#xff0c;docker启动命令 2.发现端口是8983&#xff0c;浏览器访问http://172.16.1.18:8983/ 3.用dnslog平台检测dns回显&#xff0c;看看有没有漏洞存在 4.反弹shell到kali&#xff08;ip为172.16.1.18&#xf…

【白话Spring】三级缓存

快速导航 一、Spring的三级缓存是什么&#xff1f;三级缓存SpringBean 的生命周期&#xff1a;BeanFactory关于Bean初始化注释&#xff1a;分析&#xff1a;Bean的创建过程&#xff1a;Bean的销毁过程&#xff1a; Spring Bean创建的核心逻辑&#xff1a; 二、Spring的三级缓存…

CentOS7 使用yum报错:[Errno 14] HTTP Error 404 - Not Found 正在尝试其它镜像。

CentOS7 使用yum报错&#xff1a;[Errno 14] HTTP Error 404 - Not Found 正在尝试其它镜像。 CentOS镜像下载、VM虚拟机下载 下载地址&#xff1a;www.macfxb.cn 一、问题描述 安装完CentOS7 后 使用yum报错 如下图 二、解决方案 1.查看自己的系统架构 我的是aarch64 uname …

【MySQL】查询语句之inner、left、right、full join 的区别

前言&#xff1a; INNER JOIN 和 OUTER JOIN 是SQL中常用的两种连接方式&#xff0c;用于从两表活多表中提取相关的数据。两者区别主要在于返回的 结果集 如何处理 匹配 与 不匹配 的行。 目录 1、INNER JOIN 2、OUTER JOIN 3、总结 1、INNER JOIN 称为内连接&#xff0c;只…

ComfyUI-AdvancedLivePortrait:实时编辑人脸让图像动起来

经常使用Stable Diffiusion的朋友都知道&#xff0c;webUI和comfyUI底层都是Stable Diffiusion&#xff0c;但是它们的显示界面有非常大的区别&#xff1a;webUI界面简洁&#xff0c;新手比较容易上手&#xff1b;而ComfyUI 是采用基于节点的图形界面&#xff0c;通过连接不同的…

面向 NetworkX 用户的加速生产就绪型图形分析

目录 借助 NetworkX 轻松进行图形分析 使用 cuGraph 加速图形分析 使用 ArangoDB 进行生产就绪型图形分析 借助 cuGraph 和 ArangoDB 实现 GPU 加速分析 实施示例 测试环境 下载数据 创建 NetworkX 图形 在不使用 ArangoDB 的情况下运行 cuGraph 算法 将 NetworkX 图…

【Qt 即时通讯项目】登录验证码是如何做到的呢

文章目录 1. 登录注册功能验证码实现2. 验证码生成的流程3. 细节部分 1. 登录注册功能验证码实现 &#x1f427;①目的&#xff1a;引入验证码&#xff0c;目的是用来避免程序被其它程序暴力破解的方式找到密码。 2. 验证码生成的流程 ①&#x1f34e;首先通过Qt的QRandomGen…

初始Linux 和 各种常见指令

目录 Linux背景 1. 发展史 Linux发展历史 1.历史 2. 开源 Linux下基本指令 01. ls 指令 02. pwd命令 03. cd 指令 04. touch指令 05.mkdir指令&#xff08;重要&#xff09;&#xff1a; 06.rmdir指令 && rm 指令&#xff08;重要&#xff09;&#xff1a; …