深入浅出Java反射:掌握动态编程的艺术

  • 小程一言
  • 反射
    • 何为反射
    • 反射核心类
    • 反射的基本使用
      • 获取`Class`对象
      • 创建对象
      • 调用方法
      • 访问字段
    • 示例程序
    • 应用场景
    • 优缺点分析
      • 优点
      • 缺点
    • 注意
  • 再深入一些
    • 反射与泛型
    • 反射与注解
    • 反射与动态代理
    • 反射与类加载器
  • 结语

小程一言

本专栏是对Java知识点的总结。在学习Java的过程中,学习的笔记,加入自己的思考,结合各种资料的整理。

文章与程序一样,一定都是不完美的,因为不完美,才拥有不断追求完美的动力

以下是符合您要求的博客文章,主类名为crj,内容全面细致,深度适中,字数约5000字。

---

反射

Java反射是Java语言中一项强大的功能,它允许程序在运行时动态地获取类的信息并操作类的属性、方法和构造方法。反射机制为Java提供了极大的灵活性,广泛应用于框架开发、动态代理、注解处理等场景。本文将详细介绍Java反射的核心概念、使用方法以及注意事项,并通过示例代码帮助读者更好地理解。


何为反射

简单来说,反射是指在程序运行时,能够动态地获取类的信息(如类名、方法、字段、构造方法等),并能够操作这些信息。通过反射,我们可以在运行时创建对象、调用方法、访问字段,甚至修改私有成员的值。

反射的核心类是java.lang.reflect包中的ClassMethodFieldConstructor。通过这些类,我们可以实现动态编程。

在这里插入图片描述

反射核心类

  1. Class<T>: 表示一个类或接口的类型信息。通过Class对象可以获取类的构造方法、方法和字段。
  2. Constructor<T>: 表示类的构造方法,用于创建对象。
  3. Method: 表示类的方法,用于调用方法。
  4. Field: 表示类的字段,用于访问或修改字段的值。

反射的基本使用

获取Class对象

要使用反射,首先需要获取目标类的Class对象。以下是三种常见的获取方式:

  • Class.forName("全限定类名"): 通过类的全限定名获取Class对象。
  • 对象.getClass(): 通过对象实例获取Class对象。
  • 类名.class: 直接通过类名获取Class对象。
// 示例:获取String类的Class对象
Class<?> clazz = Class.forName("java.lang.String");

创建对象

通过Class对象可以获取类的构造方法,并调用newInstance()方法创建对象。

// 示例:通过反射创建String对象
Class<?> clazz = Class.forName("java.lang.String");
Constructor<?> constructor = clazz.getConstructor(); // 获取无参构造方法
Object obj = constructor.newInstance(); // 创建对象
System.out.println("创建的对象: " + obj);

调用方法

通过Class对象可以获取类的方法,并调用invoke()方法执行方法。

// 示例:通过反射调用String的length()方法
Class<?> clazz = Class.forName("java.lang.String");
Method method = clazz.getMethod("length"); // 获取length()方法
int length = (int) method.invoke("Hello"); // 调用方法
System.out.println("字符串长度: " + length);

访问字段

通过Class对象可以获取类的字段,并访问或修改字段的值。

// 示例:通过反射访问Integer的value字段
Class<?> clazz = Class.forName("java.lang.Integer");
Field field = clazz.getDeclaredField("value"); // 获取value字段
field.setAccessible(true); // 设置可访问私有字段
int value = (int) field.get(10); // 获取字段值
System.out.println("字段值: " + value);

在这里插入图片描述

示例程序

以下是一个完整的示例程序,展示了如何使用反射创建对象、调用方法和访问字段。

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;public class crj {public static void main(String[] args) {try {// 1. 获取Class对象Class<?> clazz = Class.forName("java.lang.String");// 2. 创建对象Constructor<?> constructor = clazz.getConstructor();Object obj = constructor.newInstance();System.out.println("创建的对象: " + obj);// 3. 调用方法Method method = clazz.getMethod("length");int length = (int) method.invoke("Hello");System.out.println("字符串长度: " + length);// 4. 访问字段Class<?> integerClass = Class.forName("java.lang.Integer");Field field = integerClass.getDeclaredField("value");field.setAccessible(true);int value = (int) field.get(10);System.out.println("Integer的value字段值: " + value);} catch (Exception e) {e.printStackTrace();}}
}

应用场景

  1. 动态代理: 在运行时创建代理对象,例如Spring AOP。
  2. 框架开发: 如Spring通过反射管理Bean的生命周期。
  3. 注解处理: 在运行时读取注解信息,例如JUnit的测试框架。
  4. 工具开发: 如IDE的代码提示功能。

优缺点分析

优点

  • 灵活性高: 可以在运行时动态操作类和方法。
  • 功能强大: 适用于框架和工具开发。

缺点

  • 性能较低: 反射操作比直接调用慢。
  • 破坏封装性: 可以访问私有成员,可能导致安全问题。
  • 代码可读性差: 反射代码通常难以理解和维护。

注意

  1. 性能问题: 反射操作较慢,频繁使用时需谨慎。
  2. 安全性: 反射可以绕过访问控制,需确保代码的安全性。
  3. 异常处理: 反射操作可能抛出IllegalAccessExceptionInvocationTargetException等异常,需妥善处理。

在这里插入图片描述

再深入一些

将能联系到的地方都牵连一下,希望能给你更多的思考

反射与泛型

Java反射机制在处理泛型时需要注意类型擦除的问题。由于Java的泛型是通过类型擦除实现的,因此在运行时无法直接获取泛型的具体类型信息。但是,可以通过ParameterizedType等接口来获取泛型的信息。

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class crj{public static class GenericClass<T> {public void printType() {Type type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];System.out.println("泛型类型: " + type);}}public static void main(String[] args) {GenericClass<String> genericClass = new GenericClass<String>() {};genericClass.printType();}
}

反射与注解

Java反射机制可以用于读取和处理注解。通过反射,我们可以在运行时获取类、方法、字段上的注解信息,并根据注解的值执行相应的逻辑。

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {String value();
}public class AnnotationReflectionExample {@MyAnnotation("Hello, Annotation!")public void annotatedMethod() {System.out.println("这是一个带有注解的方法");}public static void main(String[] args) throws Exception {Method method = AnnotationReflectionExample.class.getMethod("annotatedMethod");MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);System.out.println("注解值: " + annotation.value());}
}

在这里插入图片描述

反射与动态代理

Java反射机制在动态代理中扮演着重要角色。通过Proxy类和InvocationHandler接口,我们可以在运行时创建代理对象,并在调用方法时执行额外的逻辑。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;interface MyInterface {void doSomething();
}public class DynamicProxyExample {public static void main(String[] args) {MyInterface realObject = new MyInterface() {@Overridepublic void doSomething() {System.out.println("真实对象的方法");}};MyInterface proxyObject = (MyInterface) Proxy.newProxyInstance(MyInterface.class.getClassLoader(),new Class<?>[] { MyInterface.class },new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("方法调用前");Object result = method.invoke(realObject, args);System.out.println("方法调用后");return result;}});proxyObject.doSomething();}
}

反射与类加载器

Java反射机制与类加载器密切相关。通过自定义类加载器,我们可以在运行时动态加载类,并使用反射机制操作这些类。

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.URL;public class CustomClassLoader extends ClassLoader {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {byte[] classData = loadClassData(name);return defineClass(name, classData, 0, classData.length);}private byte[] loadClassData(String className) {InputStream inputStream = getClass().getClassLoader().getResourceAsStream(className.replace('.', '/') + ".class");ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();int bufferSize = 4096;byte[] buffer = new byte[bufferSize];int bytesRead;try {while ((bytesRead = inputStream.read(buffer)) != -1) {byteArrayOutputStream.write(buffer, 0, bytesRead);}} catch (Exception e) {e.printStackTrace();}return byteArrayOutputStream.toByteArray();}public static void main(String[] args) throws Exception {CustomClassLoader customClassLoader = new CustomClassLoader();Class<?> clazz = customClassLoader.loadClass("com.example.MyClass");Object obj = clazz.getDeclaredConstructor().newInstance();Method method = clazz.getMethod("myMethod");method.invoke(obj);}
}

在这里插入图片描述

结语

Java反射是一项强大的功能,它为Java提供了动态编程的能力。通过反射,我们可以在运行时获取类的信息并操作类的成员。尽管反射具有很高的灵活性,但也存在性能和安全性的问题。在实际开发中,应根据需求合理使用反射,避免滥用。

希望本文能帮助你更好地理解Java反射机制!如果你有任何问题或建议,欢迎在评论区留言。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JDK 14,15,17的一些新特性(部分常用)

1&#xff1a;instanceof&#xff08;后&#xff0c;使用不再需要墙转&#xff09; 2&#xff1a;switch语句增强 1&#xff1a;支持lmbda&#xff0c;自动防击穿&#xff0c;有返回值 2&#xff1a;支持case多个值&#xff0c;复杂逻辑结果支持yield返回 3&#xff1a;字符串…

活字格使用说明书

字格设计使用说明书 目录 1. 数据 2. 页面 3. 组件 4. 命令 一、数据 1.表数据创建(鼠标移动到表右击点击创建表) ‘ 图表 1 鼠标移至表1右击可重命名,添加字段输入所需字段名(一般数据类型的要注意:日期格式字段---日期、ID或者字典字段---整数、金…

springboot021校园周边美食探索及分享平台

版权声明 所有作品均为本人原创&#xff0c;提供参考学习使用&#xff0c;如需要源码数据库配套文档请移步 www.taobysj.com 搜索获取 技术实现 开发语言&#xff1a;Javavue。 框架&#xff1a;后端spingboot前端vue。 模式&#xff1a;B/S。 数据库&#xff1a;mysql。 开…

Kubernetes部署KeyDB服务

Kubernetes YAML 配置文件&#xff0c;部署一个 KeyDB 容器 vi keydb-deployment.yaml内容如下 apiVersion: apps/v1 kind: Deployment metadata:name: keydb-deployment spec:replicas: 1selector:matchLabels:app: keydbtemplate:metadata:labels:app: keydbspec:container…

新手自学:如何用gromacs对简单分子复合物进行伞形采样

1、建立体系: 1、将蛋白的pdb文件转化为gmx: gmx pdb2gmx -f 2BEG_model1_capped.pdb -ignh -ter -o complex.gro 这个网页可以实现将多肽序列转化为pdb: ProBuilder On-line 这个教程的蛋白2BFG包含两条链(chain A和B) 在生成的topol文件中,增加如下的内容,效果就…

如何使用Java语言在Idea和Android中分别建立服务端和客户端实现局域网聊天

手把手教你用Java语言在Idea和Android中分别建立服务端和客户端实现局域网聊天 目录 文章目录 手把手教你用**Java**语言在**Idea**和**Android**中分别建立**服务端**和**客户端**实现局域网聊天**目录**[toc]**基本实现****问题分析****服务端**Idea:结构预览Server类代码解…

金蝶云星空与马帮平台无缝对接,提高供应链效率

采购退货金蝶》马帮ok&#xff1a;系统对接集成案例分享 在企业的供应链管理中&#xff0c;数据的高效流转和准确处理至关重要。本文将聚焦于一个实际运行的系统对接集成案例——将金蝶云星空的数据集成到马帮平台&#xff0c;以实现采购退货数据的无缝传输和处理。 为了确保…

GPT-4o微调SFT及强化学习DPO数据集构建

假设&#xff0c;已经标注的训练数据集df包含了提示词、输入和输出三列。 构建微调SFT的数据集代码如下&#xff1a; data [] for x in df.values:prompt x[1]user_content x[2]assistant_content x[3]data.append({"messages": [{"role": "sys…

鸿蒙HarmonyOS NEXT开发:横竖屏切换开发实践

文章目录 一、概述二、窗口旋转说明1、配置module.json5的orientation字段2、调用窗口的setPreferredOrientation方法 四、性能优化1、使用自定义组件冻结2、对图片使用autoResize3、排查一些耗时操作 四、常见场景示例1、视频类应用横竖屏开发2、游戏类应用横屏开发 五、其他常…

02.10 TCP之文件传输

1.思维导图 2.作业 服务器代码&#xff1a; #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> …

Qt 控件整理 —— 按钮类

一、PushButton 1. 介绍 在Qt中最常见的就是按钮&#xff0c;它的继承关系如下&#xff1a; 2. 常用属性 3. 例子 我们之前写过一个例子&#xff0c;根据上下左右的按钮去操控一个按钮&#xff0c;当时只是做了一些比较粗糙的去演示信号和槽是这么连接的&#xff0c;这次我们…

1.Excel:某停车场计划调整收费标准❗(13)

目录 函数VLOOKUP ROUNDUP/ROUNDDOWN函数 NO1​ NO2会计专用类型​ NO3收费标准VLOOKUP​ NO4停放时间&#xff08;天&#xff09;​ NO5金额roundup/rounddown​ ​NO6汇总行​ NO7单元格突出显示​ NO8数据透视表​ 函数VLOOKUP VLOOKUP(收费标准!A3:B5 F4&#xf…

玩转大语言模型——使用Kiln AI可视化环境进行大语言模型微调数据合成

系列文章目录 玩转大语言模型——使用langchain和Ollama本地部署大语言模型 玩转大语言模型——三分钟教你用langchain提示词工程获得猫娘女友 玩转大语言模型——ollama导入huggingface下载的模型 玩转大语言模型——langchain调用ollama视觉多模态语言模型 玩转大语言模型—…

OpenAI推出的Computer Use智能体:Operator是什么

OpenAI推出的Computer Use智能体:Operator是什么 是一款能像人一样与图形用户界面交互来操作计算机的AI智能体。以下是其核心原理及举例说明: 核心原理 感知: 屏幕截图获取:利用高性能屏幕捕获模块,如基于WebRTC的截图技术,以极低延迟获取高清晰度页面图像,为后续分析…

k8s部署logstash

1. 编写logstash.yaml配置文件 --- apiVersion: v1 kind: Service metadata:name: logstash spec:type: ClusterIPclusterIP: Noneports:- name: logstash-tcpport: 5000targetPort: 5000- name: logstash-beatsport: 5044targetPort: 5044- name: logstash-apiport: 9600targ…

【AI大模型】Ollama部署本地大模型DeepSeek-R1,交互界面Open-WebUI,RagFlow构建私有知识库

文章目录 DeepSeek介绍公司背景核心技术产品与服务应用场景优势与特点访问与体验各个DeepSeek-R系列模型的硬件需求和适用场景 Ollama主要特点优势应用场景安装和使用配置环境变量总结 安装open-webui下载和安装docker desktop配置镜像源安装open-webui运行和使用 RagFlow介绍主…

【办公】钉钉修改默认存储位置,释放C盘空间

Step1: 右击钉钉图标选择设置 Step2: 通用里面找到文件保存位置&#xff0c;修改文件目录: 最新版本钉钉界面&#xff1a; 设置完成后按提示重启即可&#xff01;

MVC(Model-View-Controller)framework using Python ,Tkinter and SQLite

1.项目结构 sql: CREATE TABLE IF NOT EXISTS School (SchoolId TEXT not null, SchoolName TEXT NOT NULL,SchoolTelNo TEXT NOT NULL) 整体思路 Model&#xff1a;负责与 SQLite 数据库进行交互&#xff0c;包括创建表、插入、删除、更新和查询数据等操作。View&#xff1…

MongoDB 扩缩容实战:涵盖节点配置、服务启动与移除操作

#作者&#xff1a;任少近 文章目录 一、扩容在245节点上配置配置config server&#xff1a;配置mongos启动config server安装工具mongosh添加245新节点到副本集配置分片副本集启动路由并分片 二、缩容Conf server上去掉server4shard上去掉server4mongos上去掉server4 一、扩容…

AGI时代的认知重塑:人类文明的范式转移与思维革命

文章目录 引言:站在文明转型的临界点一、认知危机:当机器开始理解世界1.1 AGI的本质突破:从模式识别到世界建模1.2 人类认知的脆弱性暴露二、认知革命:重构思维的四个维度2.1 元认知升级:从直觉思维到二阶观察2.2 混合智能:人机认知回路的构建2.3 认知安全:防御机器思维…