Java学习——day22(Java反射基础入门)

news2025/4/17 14:18:27

文章目录

  • 1.反射的定义
  • 2. 认识反射的关键API
    • 2.1 Class
    • 2.2 Field
    • 2.3 Method
    • 2.4 Constructor
  • 3. 示例代码讲解与分析
  • 4. 编写反射示例代码的步骤
    • 4.1 定义测试类
    • 4.2 编写主程序,使用反射获取信息
    • 4.3 通过反射创建对象并调用方法
  • 5. 总结
  • 6.今日生词

Java反射笔记

1.反射的定义

  • 反射是什么?
    Java反射是一种在运行时动态获取类的结构信息并操作对象的机制。通过反射,你可以:
    • 获取类信息:在程序运行时动态加载类,检查类的属性、方法和构造函数。
    • 动态操作:可以动态调用对象的方法、修改对象的属性(即使是私有成员),甚至创建新的对象实例。
  • 应用场景:
    • 框架开发(如Spring、Hibernate)常常利用反射实现依赖注入、动态代理和数据绑定。
    • 插件化开发:根据配置动态加载类,实现模块化扩展。

2. 认识反射的关键API

2.1 Class

  • 作用:代表一个类或接口的运行时类型信息。
  • 获取方式:
    • 使用实例的 getClass() 方法:Object obj = new Person(); Class<?> cls = obj.getClass();
    • 使用静态方法 Class.forName("完整类名")Class<?> cls = Class.forName("com.example.Person");
  • 常用方法:
    • getName():获取类的全限定名。
    • getDeclaredFields():获取所有声明的字段(包括私有字段)。
    • getDeclaredMethods():获取所有声明的方法。
    • getConstructors() getDeclaredConstructors():获取公共构造函数或所有构造函数。

2.2 Field

  • 作用:代表类的成员变量(字段)。
  • 常用方法:
    • getName():返回字段名称。
    • get(Object obj):获取指定对象上此字段的值。
    • set(Object obj, Object value):修改指定对象上此字段的值。
    • setAccessible(true):当字段是私有时,允许通过反射访问或修改其值。
  • 注意事项:使用 setAccessible(true) 时要注意安全性和封装性,最好在必要时才使用。

2.3 Method

  • 作用:代表类中的方法。
  • 常用方法:
  • getName():获取方法名称。
  • invoke(Object obj, Object... args):在指定对象上调用此方法,传递必要的参数。
  • getParameterTypes():获取方法参数类型数组。
  • 使用场景:动态调用对象方法,或在运行时根据方法名称决定调用哪个方法。

2.4 Constructor

  • 作用:代表类的构造函数。
  • 常用方法:
    • newInstance(Object... initargs):利用构造函数创建新实例,传入必要参数。
    • getParameterTypes():获取构造函数的参数类型。
  • 使用场景:动态创建对象实例,尤其是在编写通用工厂模式或插件式架构时非常有用。

3. 示例代码讲解与分析

下面是一段简单的示例代码,展示如何使用反射获取一个类的结构信息。假设我们有一个简单的 Person 类。
示例代码

// 定义一个简单的Person类
public class Person {
    private String name;
    private int age;

    // 构造函数
    public Person() {
        this.name = "Default";
        this.age = 0;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // 方法:打印信息
    public void sayHello() {
        System.out.println("Hello, my name is " + name);
    }
}

反射获取类信息的示例

import java.lang.reflect.*;

public class ReflectionDemo {
    public static void main(String[] args) {
        try {
            // 1. 获取Person类的Class对象
            Class<?> personClass = Class.forName("Person");

            // 2. 获取类的名称
            System.out.println("类名称:" + personClass.getName());

            // 3. 获取所有构造函数
            Constructor<?>[] constructors = personClass.getDeclaredConstructors();
            System.out.println("构造函数:");
            for (Constructor<?> constructor : constructors) {
                System.out.println("  " + constructor);
            }

            // 4. 获取所有字段(包括私有字段)
            Field[] fields = personClass.getDeclaredFields();
            System.out.println("字段:");
            for (Field field : fields) {
                System.out.println("  " + field.getName());
            }

            // 5. 获取所有方法
            Method[] methods = personClass.getDeclaredMethods();
            System.out.println("方法:");
            for (Method method : methods) {
                System.out.println("  " + method.getName());
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

分析

  • Class.forName(“Person”):动态加载 Person 类,通过其完全限定名获得 Class 对象。
  • 获取构造函数:调用 getDeclaredConstructors() 返回该类所有构造函数,并输出构造函数的签名。
  • 获取字段:调用 getDeclaredFields(),即使字段为私有也能获取到。通过 field.getName() 输出每个字段的名称。
  • 获取方法:调用 getDeclaredMethods() 得到类中所有声明的方法,输出方法名称以便了解类提供了哪些操作。

4. 编写反射示例代码的步骤

4.1 定义测试类

创建一个名为 Person 的类,包含如下内容:

  • 字段:name(String)、age(int)。
  • 构造函数:无参构造函数和带参构造函数。
  • 方法:例如 sayHello() 用于输出欢迎信息。

4.2 编写主程序,使用反射获取信息

1.加载类:使用 Class.forName("Person") 获取 Class 对象。
2.获取构造函数:使用 getDeclaredConstructors() 获取所有构造函数。
3.获取字段:使用 getDeclaredFields() 获取所有字段,必要时调用 setAccessible(true) 访问私有字段。
4.获取方法:使用getDeclaredMethods()获取所有方法。

4.3 通过反射创建对象并调用方法

  • 实例化对象:使用获取到的构造函数(如带参构造函数)调用 newInstance() 创建 Person 对象。
  • 修改字段:如果需要,可以通过反射修改私有字段的值。例如,调用 field.setAccessible(true) 后,再使用 field.set(personInstance, "新的名字")
  • 调用方法:使用 Method.invoke(object, args...) 来调用 sayHello() 方法,并观察控制台输出。

示例代码扩展:创建对象并调用方法


import java.lang.reflect.*;

public class ReflectionDemoExtended {
    public static void main(String[] args) {
        try {
            // 1. 加载Person类的Class对象
            Class<?> personClass = Class.forName("Person");

            // 2. 获取带参构造函数,并创建对象
            Constructor<?> constructor = personClass.getConstructor(String.class, int.class);
            Object personInstance = constructor.newInstance("Alice", 25);

            // 3. 修改私有字段(假设需要修改name)
            Field nameField = personClass.getDeclaredField("name");
            nameField.setAccessible(true); // 允许访问私有字段
            nameField.set(personInstance, "Bob");

            // 4. 调用sayHello方法
            Method sayHelloMethod = personClass.getDeclaredMethod("sayHello");
            sayHelloMethod.invoke(personInstance);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

代码说明

  • 创建对象:通过 getConstructor(String.class, int.class) ``获取带参构造函数,然后调用 newInstance(“Alice”, 25) `创建对象。
  • 修改字段:通过 getDeclaredField("name") 获取 name 字段,设置为可访问后,用 set() 方法修改对象的 name 值为 “Bob”。
  • 调用方法:获取 sayHello 方法,并调用 invoke() 执行该方法,观察输出验证修改后的值。

5. 总结

  • 反射的优势:可以在运行时动态操作对象和类,灵活应对各种需求(如插件化、依赖注入)。
  • 需要注意的点:
    • 反射操作可能破坏封装性,使用时需要谨慎。
    • 反射会有一定的性能损耗,不建议在性能敏感的场景中大量使用。

6.今日生词

1.tongue 2.circunstance 3.tension 4.economist 5.accommodate

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

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

相关文章

BN 层做预测的时候, 方差均值怎么算

✅ 一、Batch Normalization&#xff08;BN&#xff09;回顾 BN 层在训练和推理阶段的行为是不一样的&#xff0c;核心区别就在于&#xff1a; 训练时用 mini-batch 里的均值方差&#xff0c;预测时用全局的“滑动平均”均值方差。 &#x1f9ea; 二、训练阶段&#xff08;Trai…

JS 其他事件类型

页面加载 事件 window.addEvent() window.addEventListener(load,function(){const btn document.querySelector(button)btn.addEventListener(click,function(){alert(按钮)})})也可以给其他标签加该事件 HTML加载事件 找html标签 也可以给页面直接赋值

AI Agent设计模式五:Orchestrator

概念 &#xff1a;中央任务调度中枢 ✅ 优点&#xff1a;全局资源协调&#xff0c;确保任务执行顺序❌ 缺点&#xff1a;单点故障风险&#xff0c;可能成为性能瓶颈 import operator import osfrom langchain.schema import SystemMessage, HumanMessage from langchain_opena…

MySQL基础 [三] - 数据类型

目录 数据类型分类 ​编辑 数值类型 tinyint bit 浮点类型 float decimal 字符串类型 char varchar varchar和char的比较和选择 日期和时间类型 enum和set enum类型 set类型 enum和set的类型查找 数据类型分类 数值类型 tinyint TINYINT[(M)] [UNSIGNED]是 …

不用训练,集成多个大模型产生更优秀的输出

论文标题 Collab: Controlled Decoding using Mixture of Agents for LLM Alignment 论文地址 https://arxiv.org/pdf/2503.21720 作者背景 JP摩根&#xff0c;马里兰大学帕克分校&#xff0c;普林斯顿大学 动机 大模型对齐&#xff08;alignment&#xff09;的主要目的…

随笔1 认识编译命令

1.认识编译命令 1.1 解释gcc编译命令: gcc test1.cpp -o test1 pkg-config --cflags --libs opencv 命令解析&#xff1a; gcc&#xff1a;GNU C/C 编译器&#xff0c;用于编译C/C代码。 test1.cpp&#xff1a;源代码文件。 -o test1&#xff1a;指定输出的可执行文件名为t…

Hyperlane 框架路由功能详解:静态与动态路由全掌握

Hyperlane 框架路由功能详解&#xff1a;静态与动态路由全掌握 Hyperlane 框架提供了强大而灵活的路由功能&#xff0c;支持静态路由和动态路由两种模式&#xff0c;让开发者能够轻松构建各种复杂的 Web 应用。本文将详细介绍这两种路由的使用方法。 静态路由&#xff1a;简单…

铰链损失函数 Hinge Loss和Keras 实现

一、说明 在为了了解 Keras 深度学习框架的来龙去脉&#xff0c;本文介绍铰链损失函数&#xff0c;然后使用 Keras 实现它们以进行练习并了解它们的行为方式。在这篇博客中&#xff0c;您将首先找到两个损失函数的简要介绍&#xff0c;以确保您在我们继续实现它们之前直观地理解…

瑞数信息发布《BOTS自动化威胁报告》,揭示AI时代网络安全新挑战

近日&#xff0c;瑞数信息正式发布《BOTS自动化威胁报告》&#xff0c;力求通过全景式观察和安全威胁的深度分析&#xff0c;为企业在AI时代下抵御自动化攻击提供安全防护策略&#xff0c;从而降低网络安全事件带来的影响&#xff0c;进一步增强业务韧性和可持续性。 威胁一&am…

FLV格式:流媒体视频的经典选择

FLV格式&#xff1a;流媒体视频的经典选择 FLV&#xff08;Flash Video&#xff09;格式曾经是流媒体视频的主力军&#xff0c;在互联网视频的早期时代广泛应用于视频网站和多媒体平台。凭借其高效的压缩和较小的文件体积&#xff0c;FLV成为了许多视频内容创作者和平台的首选…

需求分析-用例图绘制、流程图绘制

第一&#xff0c;引论 需求分析是开发的第一步&#xff0c;也是我个人认为最重要的一步。 技术难题的克服&#xff0c;甚至在我心里&#xff0c;还要排在需求分析后面。 如果需求分析做好了&#xff0c;数据库就更容易建立&#xff0c;数据库建好了&#xff0c;业务逻辑写起…

Windows安装 PHP 8 和mysql9,win下使用phpcustom安装php8.4.5和mysql9

百度搜索官网并下载phpcustom&#xff0c;然后启动环境&#xff0c;点击网站管理 里面就有php8最新版&#xff0c;可以点mysql设置切mysql9最新版&#xff0c;如果你用最新版无法使用&#xff0c;说明你的php程序不支持最新版的mysql MySQL 9.0 引入了一些新的 SQL 模式和语法变…

http://noi.openjudge.cn/_2.5基本算法之搜索_1804:小游戏

文章目录 题目深搜代码宽搜代码深搜数据演示图总结 题目 1804:小游戏 总时间限制: 1000ms 内存限制: 65536kB 描述 一天早上&#xff0c;你起床的时候想&#xff1a;“我编程序这么牛&#xff0c;为什么不能靠这个赚点小钱呢&#xff1f;”因此你决定编写一个小游戏。 游戏在一…

手写JSX实现虚拟DOM

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…

Spring Boot 中的 Bean

2025/4/6 向全栈工程师迈进&#xff01; 一、Bean的扫描 在之前&#xff0c;对于Bean的扫描&#xff0c;我们可以在XML文件中书写标签&#xff0c;来指定要扫描的包路径&#xff0c;如下所示,可以实通过如下标签的方式&#xff1a; <context:component-scan base-package&…

ST 芯片架构全景速览:MCU、无线 SoC、BLE 模块、MPU 差异详解

在嵌入式开发中,ST 是一个非常常见的芯片厂商,其产品线覆盖了 MCU、无线芯片、BLE 模块以及运行 Linux 的 MPU 等多个领域。很多开发者初次接触 ST 时会对这些产品之间的关系感到困惑。 本文从分类视角出发,带你快速了解 ST 芯片家族的核心架构和主要用途。 🧭 ST 芯片四…

AtCoder Beginner Contest 400(ABCDE)

A - ABC400 Party 翻译&#xff1a; 在 ABC400 的纪念仪式上&#xff0c;我们想把 400 人排成 A 行 B 列的长方形&#xff0c;且不留任何空隙。 给你一个正整数 A&#xff0c;请打印可以这样排列的正整数 B 的值。如果没有这样的正整数 B&#xff0c;则打印-1。 思路&#xff…

Flask+Vue构建图书管理系统及Echarts组件的使用

教程视频链接从零开始FlaskVue前后端分离图书管理系统 后端 项目下载地址 其中venv为该项目的虚拟环境&#xff0c;已安装所有依赖 使用方法&#xff1a; 在pycharm终端中flask create一下&#xff08;因为写了一个自定义命令的代码&#xff09;&#xff0c;初始化books数据…

【项目管理】第2章 信息技术发展 --知识点整理

Oracle相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 (一)知识总览 对应:第1章-第5章 (二)知识笔记 二、信息技术的发展 1. 信息技术及其发展 1)计算机软硬件 计算机硬件由电子机械、光电元件等组成的物理装置,提供物质基础给计算机软件运行。软件包括程…

4-c语言中的数据类型

一.C 语⾔中的常量 1.生活中的数据 整数&#xff1a; 100,200,300,400,500 小数: 11.11 22.22 33.33 字母&#xff1a; a&#xff0c;b&#xff0c;c&#xff0c;d A&#xff0c;B&#xff0c;C&#xff0c;D 在 C 语⾔中我们把字⺟叫做字符. 字符⽤单引号引⽤。例如A’ 单词…