Java零基础-反射

哈喽,各位小伙伴们,你们好呀,我是喵手。

  今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。

  我是一名后端开发爱好者,工作日常接触到最多的就是Java语言啦,所以我都尽量抽业余时间把自己所学到所会的,通过文章的形式进行输出,希望以这种方式帮助到更多的初学者或者想入门的小伙伴们,同时也能对自己的技术进行沉淀,加以复盘,查缺补漏。

小伙伴们在批阅的过程中,如果觉得文章不错,欢迎点赞、收藏、关注哦。三连即是对作者我写作道路上最好的鼓励与支持!

前言

Java是目前最流行的开发语言之一,在软件开发领域广泛应用。反射是Java的一项重要特性,它使得程序在运行时可以动态地获取和操作类、方法、属性等信息,极大地提高了Java的灵活性和可扩展性。

本文将介绍Java反射的基本概念、使用方法、应用场景和优缺点,旨在为Java初学者提供一份简明易懂的指南。

摘要

本文主要分为以下几个部分:首先介绍Java反射的基本概念;然后通过源代码解析,详细讲解如何使用反射获取类信息、创建对象、调用方法、访问属性等;接着根据实际应用场景,分析了反射技术的优缺点;最后给出了类代码方法介绍和测试用例,以便读者更好地理解和实践Java反射。

简介

Java反射机制是指在程序运行时,对于任意一个类都能够知道这个类的所有属性和方法,对于任意一个对象都能够调用它的任意一个方法和属性。它是Java的一项重要特性,提高了程序的灵活性和可扩展性,常用于框架设计、动态代理、编译器等领域。

反射是Java语言反映本身特点的体现之一,Java语言必须在虚拟机中进行运行,所以Java程序会首先被编译成字节码,然后由虚拟机进行解释执行。这种运行方式决定了Java程序可以在运行时获取自身的信息,这种自我描述的能力就是Java反射机制。

源代码解析

Java反射主要包括以下几个步骤:获取Class对象、创建对象、调用方法、访问属性。下面分别进行详细解析。

获取Class对象

在Java中,如果要使用反射机制,首先需要获取到要操作的类的Class对象。Class对象是由JVM在加载类时自动创建的,可以通过以下几种方法获取:

方法一:使用.class语法

这是最常用的获取Class对象的方法,通过类名后面加上".class"即可。例如:

Class<?> clazz = String.class;
方法二:使用Class.forName()方法

这个方法会动态地加载类并返回Class对象。例如:

Class<?> clazz = Class.forName("java.lang.String");
方法三:使用对象的.getClass()方法

可以通过对象的getClass()方法来获取Class对象。例如:

String str = "Hello, world!";
Class<?> clazz = str.getClass();

创建对象

获取到Class对象之后,可以通过它来创建对象。创建对象有两种方法:

方法一:使用Class.newInstance()方法

通过Class对象的newInstance()方法可以直接创建对象,前提是该类必须有一个无参构造方法。例如:

Class<?> clazz = String.class;
String str = (String) clazz.newInstance();
方法二:使用Constructor对象

如果想要创建有参构造方法的对象,可以先获取Constructor对象,然后使用它来创建对象。例如:

Class<?> clazz = String.class;
Constructor<?> constructor = clazz.getConstructor(String.class);
String str = (String) constructor.newInstance("Hello, world!");

调用方法

通过Java反射机制,可以在运行期间执行任意一个类的方法。调用方法的步骤如下:

步骤一:获取Method对象

可以通过Class对象的getDeclaredMethod()或getMethod()方法来获取Method对象。前者可以获取私有方法,后者只能获取公共方法。例如:

Class<?> clazz = String.class;
Method method = clazz.getMethod("length");
步骤二:调用Method对象的invoke()方法

调用Method对象的invoke()方法可以执行方法,前提是该方法的调用者对象已经初始化。例如:

Class<?> clazz = String.class;
Method method = clazz.getMethod("length");
String str = "Hello, world!";
int length = (int) method.invoke(str);

访问属性

通过Java反射机制,可以在运行期间访问任意一个类的属性。访问属性的步骤如下:

步骤一:获取Field对象

可以通过Class对象的getDeclaredField()或getField()方法来获取Field对象。前者可以获取私有属性,后者只能获取公共属性。例如:

Class<?> clazz = String.class;
Field field = clazz.getDeclaredField("value");
步骤二:调用Field对象的get()或set()方法

调用Field对象的get()或set()方法可以获取或设置属性的值,前提是该属性的访问权限允许。例如:

Class<?> clazz = String.class;
Field field = clazz.getDeclaredField("value");
String str = "Hello, world!";
char[] value = (char[]) field.get(str);
value[6] = ',';
System.out.println(str);  // Hello, world!

应用场景案例

Java反射机制常用于以下场景:

  1. 框架设计:例如Spring框架,通过反射技术实现类的自动装配、动态代理等功能。
  2. 动态代理:例如Java自带的代理类,通过反射机制生成代理对象,然后在代理对象中调用真正的方法和属性。
  3. 编译器:例如Java编译器,通过反射技术读取和分析类文件,然后生成字节码。

优缺点分析

Java反射机制有以下优点:

  1. 灵活性高:可以在运行时动态地获取和操作类、方法、属性等信息,提高程序的灵活性和可扩展性。
  2. 可以减少重复代码:例如Spring框架中的类自动装配功能,通过反射技术可以避免大量繁琐的手动装配工作。
  3. 动态性强:可以在程序运行时动态地加载、卸载、更新类文件,实现热部署等功能。

但是Java反射机制也有以下缺点:

  1. 性能较低:反射机制中涉及到的类加载、方法调用、字段访问等操作都比较耗时,容易造成性能瓶颈。
  2. 安全性较低:反射机制可以绕过Java的访问控制机制,直接访问私有方法和属性,容易造成安全隐患。

因此,在使用Java反射机制时,需要根据实际情况进行权衡,避免滥用而造成不必要的性能和安全问题。

类代码方法介绍

代码实现了获取Class对象、创建对象、调用方法、访问属性等基本操作。

public class ReflectionDemo {public static void main(String[] args) throws Exception {// 获取Class对象的三种方法Class<?> clazz1 = String.class;Class<?> clazz2 = Class.forName("java.lang.String");String str = "Hello, world!";Class<?> clazz3 = str.getClass();// 创建对象的两种方法String str1 = (String) clazz1.newInstance();Constructor<?> constructor = clazz2.getConstructor(String.class);String str2 = (String) constructor.newInstance("Hello, world!");// 调用方法Method method = clazz1.getMethod("length");int length = (int) method.invoke(str);// 访问属性Field field = clazz1.getDeclaredField("value");field.setAccessible(true);char[] value = (char[]) field.get(str);value[6] = ',';System.out.println(length);  // 13System.out.println(str);    }
}
## 测试用例下面给出一组测试用例,以便读者更好地理解和实践Java反射。```java
public class ReflectionTest {private String name;public int age;public ReflectionTest(String name, int age) {this.name = name;this.age = age;}private void privateMethod() {System.out.println("This is a private method.");}public void publicMethod() {System.out.println("This is a public method.");}public static void main(String[] args) throws Exception {// 获取Class对象Class<?> clazz = ReflectionTest.class;// 创建对象Constructor<?> constructor = clazz.getConstructor(String.class, int.class);ReflectionTest test = (ReflectionTest) constructor.newInstance("John", 20);// 调用私有方法Method privateMethod = clazz.getDeclaredMethod("privateMethod");privateMethod.setAccessible(true);privateMethod.invoke(test);// 调用公共方法Method publicMethod = clazz.getMethod("publicMethod");publicMethod.invoke(test);// 访问公共属性Field publicField = clazz.getField("age");System.out.println("The age is " + publicField.get(test));// 访问私有属性Field privateField = clazz.getDeclaredField("name");privateField.setAccessible(true);privateField.set(test, "Tom");System.out.println("The name is " + privateField.get(test));}
}

测试结果如下:

This is a private method.
This is a public method.
The age is 20
The name is Tom

可以看到,通过Java反射机制,我们成功获取了ReflectionTest类的Class对象,创建了ReflectionTest对象,调用了私有方法、公共方法,访问了公共属性、私有属性,并成功地修改了私有属性的值。

结论

Java反射机制是Java语言的一项重要特性,可以在运行时动态地获取和操作类、方法、属性等信息,提高程序的灵活性和可扩展性。但是反射机制也有性能较低、安全性较低等缺点,需要谨慎使用。在实际应用中,可以根据需求和优缺点进行权衡,在合适的场景下选择使用Java反射技术,以便更好地满足业务需求。

… …

文末

好啦,以上就是我这期的全部内容,如果有任何疑问,欢迎下方留言哦,咱们下期见。

… …

学习不分先后,知识不分多少;事无巨细,当以虚心求教;三人行,必有我师焉!!!

wished for you successed !!!


⭐️若喜欢我,就请关注我叭。

⭐️若对您有用,就请点赞叭。

⭐️若有疑问,就请评论留言告诉我叭。

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

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

相关文章

springboot/ssm供应商管理系统Java货物进销存管理系统web

springboot/ssm供应商管理系统Java货物进销存管理系统web 基于springboot(可改ssm)vue项目 开发语言&#xff1a;Java 框架&#xff1a;springboot/可改ssm vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&#xff1a;mysq…

传感器---触摸传感器

一、模块选型概述 芯片型号&#xff1a;TTP223B 供电电压&#xff1a;3-5V 控制接口&#xff1a;共三个引脚&#xff08;GND、VCC、SIG&#xff09;&#xff0c;GND为地&#xff0c;VCC为供电电源&#xff0c;SIG为数字信号输出脚&#xff1b; PCB尺寸&#xff1a;24 x 24 mm 触…

图像传感器与信号处理——SFR算法/ISO 12233解读

图像传感器与信号处理——SFR算法/ISO 12233解读 图像传感器与信号处理——SFR算法/ISO 12233解读 1. 前言 2. 基于视觉的分辨率测量方法 3. 基于边界的SFR算法 4. 基于正弦波的SFR算法 图像传感器与信号处理——SFR算法/ISO 12233解读 SFR的全称是Spatial Frequency Response&…

蓝桥集训之统计子矩阵

统计子矩阵 核心思想&#xff1a;矩阵前缀和 双指针 用i和j双指针 遍历所有子矩阵的列用s和t双指针 遍历所有子矩阵的行求其子矩阵的和 若>k 将s向下移动 矩阵和必定减小(元素个数减少)直到满足<k 因为列一定 行数即为方案数(从t行往上数到s行 共t-s1个区间[t,t][t-1,t]…

PESTEL分析

PESTEL分析是一种用于评估宏观环境对组织或企业的影响的工具。PESTEL是对政治、经济、社会、技术、环境和法律六个方面进行分析的首字母缩写。 - 政治因素&#xff08;Political&#xff09;&#xff1a;涉及政府政策、政治稳定性、法律和法规等因素对企业的影响。 - 经济因素&…

Linux中服务端开发

1 创建socket,返回一个文件描述符lfd---socket(); 2 将lfd和IP&#xff0c;PROT进行绑定---bind(); 3 将lfd由主动变成被动监听---listen(); 4 接收一个新的连接&#xff0c;得到一个的文件描述符cfd--accept() --该文件描述符用于与客户端通信 5 while(1) { 接受数据&a…

MySQL——存储引擎

存储引擎 InnoDB 是 MySQL 默认的存储引擎&#xff0c;只有在需要它不支持的特性时&#xff0c;才会考虑其他存储引擎 实现了 4 个标准的隔离级别&#xff0c;默认级别可重复度。在可重复度隔离级别下&#xff0c;通过 MVCC 间隙锁防止幻读 主索引是聚簇索引 内部做了很多…

Docker 日志存储大小限制,默认会充爆磁盘

背景 在容器化部署的时候&#xff0c;因为没有指定日志的最大存储时间&#xff0c;导致磁盘被充爆。查看日志 一般使用docker logs -f --tail 行数 容器名称 来查看容器的运行日志&#xff0c;但是在容器被初始化的时候&#xff0c;需要指定日志的最大存储时间&#xff0c;因为…

React学习笔记

1、React初步认识 React构建Web和原生交互界面的库,相较于其它前端框架的优势,具有丰富的生态跨平台支持。 1.1、React的开发依赖 开发React必须依赖三个库: react:包含react所必须的核心代码;react-dom:react渲染在不同平台所需要的核心代码 ;babel:将jsx转换成Rea…

白云山板蓝根,一年四季都得备着

上班半年&#xff0c;每天都感觉在行尸走肉&#xff0c;长时间地坐在电脑前真的不行&#xff01;身体越来越差&#xff0c;面相也越来越糟糕&#xff0c;不仅有黑眼圈&#xff0c;痘痘也冒出来了不少&#xff0c;堪比整容&#xff0c;朋友们都纷纷调侃我&#xff0c;说我上半年…

限流、流量削峰?

学MQ的时候&#xff0c;经常会有人拿秒杀这个场景去介绍流量削峰。这很好理解&#xff0c;将请求放到一个中转站去暂存&#xff0c;虽然生产者生产很快&#xff0c;但消费者可以慢慢去中转站获取。 关于限流&#xff0c;之前一直以为限流的思想类似MQ&#xff0c;不过是内存中…

网络安全: Kali Linux 使用 docker-compose 部署 openvas

目录 一、实验 1.环境 2.Kali Linux 安装docker与docker-compose 3.Kali Linux 使用docker-compose方式部署 openvas 4. KaliLinux 使用openvas 二、问题 1. 信息安全漏洞库 2.信息安全漏洞共享平台 3.Windows 更新指南与查询 4.CVE 查询 5.docker-compose 如何修改o…

前后端分离项目Docker部署指南(上)

目录 前言 一.搭建局域网 1.搭建net-ry局域网&#xff0c;用于部署若依项目 2.注意点 二.安装redis 创建目录 将容器进行挂载 ​编辑 测试是否安装成功 ​编辑 三. 安装MySQL 创建文件夹 上传配置文件并且修改 .启动MySQL容器服务 充许远程连接 四.部署后端 使用…

LLVM clang_tokenize 的示例

1&#xff0c; 环境搭建 如同上篇 git clong llvm-project git checkout llmvorg-3.4.0 # or llvmorg-18.1.rc /bin/bash ./confiure --prefix....... # or cmake Debug make -j32 make -j install 2&#xff0c; 示例代码 Makefile&#xff1a;如同上篇 LLVM_CON…

机器学习中的 K-均值聚类算法及其优缺点。

K-均值聚类算法是一种常用的无监督学习算法&#xff0c;用于将数据集划分为K个不重叠的类别。该算法基于数据点之间的距离度量&#xff0c;通过不断迭代的方式将数据点分配给最近的聚类中心&#xff0c;并更新聚类中心的位置&#xff0c;直到达到收敛条件或最大迭代次数。 K-均…

关于“定时器中断干扰串口中断,导致串口中断数据接收不完整”的问题

问题描述 最近在做的项目&#xff0c;基于modbusRTU&#xff0c;上位机通过wifi模块给单片机发数据。 上位机每隔100ms&#xff0c;周期性发送0x03和0x10。 因为要及时的处理上位机发来的指令&#xff0c;我是在一个10ms的定时器中断中进行modbus数据处理。这就导致一个问题&…

MySQL JSON 路径表达式语法

MySQL JSON 路径表达式语法 语法 MySQL中支持的许多JSON函数&#xff0c;需要路径表达式以便识别JSON文档中的特定元素。路径由路径的作用域和一个或多个路径段组成。在MySQL JSON函数中使用的路径中&#xff0c;作用域始终是正在搜索或以其他方式操作的文档&#xff0c;由前…

NOIP 2010普及组初赛试题及解析

NOIP 2010普及组初赛试题及解析 一. 单项选择题 &#xff08;共20题&#xff0c;每题1.5分&#xff0c;共计30分。每题有且仅有一个正确答案.&#xff09;。二. 问题求解&#xff08;共2题&#xff0c;每题5分&#xff0c;共计10分&#xff09;三. 阅读程序写结果&#xff08;共…

AcWing 803. 区间合并

Problem: AcWing 803. 区间合并 文章目录 思路解题方法复杂度Code 思路 这是一个区间合并的问题。我们需要找出尽可能多的不相交的区间。首先&#xff0c;我们将所有的区间按照左端点从小到大进行排序。然后&#xff0c;我们遍历所有的区间&#xff0c;如果当前区间的左端点大于…

什么是Redis?|介绍与使用及特点浅记

Redis简介 Redis&#xff08;Remote Dictionary Server&#xff09;是一种基于内存、支持持久化的键值对存储系统&#xff0c;具有丰富的数据结构和高性能的特性。它不仅可以作为数据库&#xff0c;还可以作为缓存和消息中间件使用。Redis是单线程模型&#xff0c;但利用IO多路…