当前位置: 首页 > news >正文

android反射详解

1,反射的定义

一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的,并且能够获得此类的引用。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作。

反射则是一开始并不知道我要初始化的类对象是什么,自然也无法使用 new 关键字来创建对象了。这时候,我们使用 JDK 提供的反射 API 进行反射调用。反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。是Java被视为动态语言的关键。

Java反射机制主要提供了以下功能:

①在运行时构造任意一个类的对象

②在运行时获取或者修改任意一个类所具有的成员变量和方法

③在运行时调用任意一个对象的方法(属性)

2,Class

反射始于Class,Class是一个类,封装了当前对象所对应的类的信息。

一个类中有属性,方法,构造器等,比如说 有一个Person类,一个Order类,一个Book类,这些都是不同的类,现在需要一个类,用来描述类,这就是 Class,它应该有类名,属性,方法,构造器等。Class是用来描述类的类。

Class类是一个对象照镜子的结果,对象可以看到自己有哪些属性,方法,构造器,实现了哪些接口等等。对于每 个类而言,JRE 都为其保留一个不变的 Class 类型的对象。一个 Class 对象包含了特定某个类的有关信息。 对象只 能由系统建立对象,一个类(而不是一个对象)在 JVM 中只会有一个Class实例

2.1获取Class对象

获取Class对象的三种方式

①. 通过类名获取 类名.class

②. 通过对象获取 对象名.getClass()

③. 通过全类名获取 Class.forName(全类名) classLoader.loadClass(全类名)

例如获取People的Class对象:

public class People {private String name;private int age;public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public int getAge() {return age;}
}

通过三种方式获取: 

//方式一 通过类名获取 类名.class
Class<People> peopleClass = People.class;//方式二 通过对象获取 对象名.getClass()
People people =new People();
Class<? extends People> peopleClass1 = people.getClass();//方式三 通过全类名获取 Class.forName(全类名) classLoader.loadClass(全类名)
try {Class<?> peopleClass2 = Class.forName("com.yuanzhen.People");
} catch (ClassNotFoundException e) {throw new RuntimeException(e);
}

方式一需要导入类的包,依赖太强,不导包就抛编译错误

方式二一般可以创建对象就不需要反射了

方式三最常用,没有依赖性

2.2判断是否为某个类的实例

//peopleClass 是否为People.class的实例
boolean assignableFrom = peopleClass.isAssignableFrom(People.class);

2.3创建实例

通过反射来生成对象主要有两种方式:

①使用Class对象的newInstance()方法来创建Class对象对应类的实例。

②先通过Class对象获取指定的Constructor对象,再调用Constructor对象的newInstance()方法来创建实例。这 种方法可以用指定的构造器构造类的实例。

例如:

//方式一 使用Class对象的newInstance()方法来创建Class对象对应类的实例
try {People people1 = peopleClass.newInstance();
} catch (IllegalAccessException e) {throw new RuntimeException(e);
} catch (InstantiationException e) {throw new RuntimeException(e);
}
//方式二 先通过Class对象获取指定的Constructor对象
//再调用Constructor对象的newInstance()方法来创建实例
//这种方法可以用指定的构造器构造类的实例
Constructor<People> constructor = null;
try {constructor = peopleClass.getConstructor(People.class);constructor.newInstance();
} catch (Exception e) {throw new RuntimeException(e);
}

3,构造器

上面提到了通过构造器可以创建对象,那么怎么获得构造器呢?

获得构造器的api:

Constructor getConstructor(Class[] params)获得使用特殊的参数类型的public构造函数(包括父类)
Constructor[] getConstructors()获得类的所有公共构造函数
Constructor getDeclaredConstructor(Class[] params)获得使用特定参数类型的构造函数(包括私有)
Constructor[] getDeclaredConstructors()获得类的所有构造函数(与接入级别无关)

例如:

public class People {public People(String name, int age) {this.name = name;this.age = age;}private People() {}public People(String name) {this.name = name;}
}
try {//获取Class对象Class<?> peopleClass = Class.forName("com.yuanzhen.People");//获得使用特殊的参数类型的public构造函数(包括父类)Constructor<?> constructor = peopleClass.getConstructor(String.class, int.class);//获得使用特定参数类型的构造函数(包括私有)constructor = peopleClass.getDeclaredConstructor();//获得类的所有公共构造函数Constructor<?>[] constructors = peopleClass.getConstructors();//获得类的所有构造函数(与接入级别无关)constructors = peopleClass.getDeclaredConstructors();
} catch (Exception e) {throw new RuntimeException(e);
}

4,成员变量

4.1获取成员变量

获取类的成员变量的api:

Field getField(String name)获得命名的公共字段
Field[] getFields()获得类的所有公共字段
Field getDeclaredField(String name)获得类声明的命名的字段
Field[] getDeclaredFields()获得类声明的所有字段

例如:

public class People {public String name;private int age;public void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public int getAge() {return age;}
}
try {//获取Class对象Class<?> peopleClass = Class.forName("com.yuanzhen.People");//获得命名的公共字段  nameField field = peopleClass.getField("name");//获得类声明的命名的字段(包括私有) ageField field1 = peopleClass.getDeclaredField("age");//获得类的所有公共字段Field[] fields = peopleClass.getFields();//获得类声明的所有字段Field[] fields1 = peopleClass.getDeclaredFields();
} catch (Exception e) {throw new RuntimeException(e);
}

4.2调用成员变量

将成员变量赋值:

try {//获取Class对象Class<?> peopleClass = Class.forName("com.yuanzhen.People");//获得命名的公共字段  nameField field = peopleClass.getField("name");//获得类声明的命名的字段(包括私有) ageField field1 = peopleClass.getDeclaredField("age");//创建对象Object people = peopleClass.newInstance();//暴力反射,解除私有限定field1.setAccessible(true);//将年龄设为20field1.set(people,20);//将姓名设为张三field.set(people,"张三");
} catch (Exception e) {throw new RuntimeException(e);
}

5,成员方法

5.1获取成员方法

获取方法信息的api:

Method getMethod(String name, Class[] params)使用特定的参数类型,获得命名的公共方法
Method[] getMethods()获得类的所有公共方法
Method getDeclaredMethod(String name, Class[] params)使用特写的参数类型,获得类声明的命名的方法
Method[] getDeclaredMethods()获得类声明的所有方法

例如:

public class People {public String name;private int age;private void setName(String name) {this.name = name;}public void setAge(int age) {this.age = age;}private String getName() {return name;}public int getAge() {return age;}
}
try {//获取Class对象Class<?> peopleClass = Class.forName("com.yuanzhen.People");//使用特定的参数类型,获得命名的公共方法Method method = peopleClass.getMethod("setAge", int.class);//使用特写的参数类型,获得类声明的命名的方法(包括私有)Method method1 = peopleClass.getDeclaredMethod("setName", String.class);//获得类的所有公共方法Method[] methods = peopleClass.getMethods();//获得类声明的所有方法(包括私有)Method[] methods1 = peopleClass.getDeclaredMethods();} catch (Exception e) {throw new RuntimeException(e);
}

5.2调用成员方法

try {//获取Class对象Class<?> peopleClass = Class.forName("com.yuanzhen.People");//使用特定的参数类型,获得命名的公共方法Method method = peopleClass.getMethod("setAge", int.class);//使用特写的参数类型,获得类声明的命名的方法(包括私有)Method method1 = peopleClass.getDeclaredMethod("setName", String.class);//创建对象实例Object people = peopleClass.newInstance();//暴力反射,解除私有限定method.setAccessible(true);//调用方法setAgemethod.invoke(people,20);//调用方法 setNamemethod1.invoke(people,"张三");
} catch (Exception e) {throw new RuntimeException(e);
}

6,总结

反射的常规使用就是这些,本文主要是对常用反射api的记录总结。

相关文章:

android反射详解

1&#xff0c;反射的定义 一般情况下&#xff0c;我们使用某个类时必定知道它是什么类&#xff0c;是用来做什么的&#xff0c;并且能够获得此类的引用。于是我们直接对这个类进行实例化&#xff0c;之后使用这个类对象进行操作。 反射则是一开始并不知道我要初始化的类对象是…...

Python 反射和动态执行

反射主要应用于类的对象上&#xff0c;在运行时&#xff0c;将对象中的属性和方法反射出来&#xff0c;通过字符串对对象成员&#xff08;属性、方法&#xff09;进行查找、获取、删除、添加成员等动作&#xff0c;是一种基于字符串的事件驱动技术。 python是一门动态语言&…...

计算机网络常见端口号

端口号标识了一个主机上进行通信的不同的应用程序。比如网站服务器80端口一般都是开启的&#xff0c;等你来连接。 端口划分&#xff1a; &#xff08;1&#xff09;常用端口&#xff0c;公共端口&#xff08;保留给公共服务所使用&#xff09;&#xff0c;端口号为0-1023之间…...

SpringBoot / Vue 对SSE的基本使用(简单上手)

一、SSE是什么&#xff1f; SSE技术是基于单工通信模式&#xff0c;只是单纯的客户端向服务端发送请求&#xff0c;服务端不会主动发送给客户端。服务端采取的策略是抓住这个请求不放&#xff0c;等数据更新的时候才返回给客户端&#xff0c;当客户端接收到消息后&#xff0c;…...

Qt串口基本设置与协议收发

前言 1.一直都想要做一个Qt上位机&#xff0c;趁着这个周末有时间&#xff0c;动手写一下 2.comboBox没有点击的信号&#xff0c;所以做了一个触发的功能 3.Qt的数据类型很奇怪&#xff0c;转来转去的我也搞得很迷糊 4.给自己挖个坑&#xff0c;下一期做一个查看波形的上位…...

interview3-微服务与MQ

一、SpringCloud篇 &#xff08;1&#xff09;服务注册 常见的注册中心&#xff1a;eureka、nacos、zookeeper eureka做服务注册中心&#xff1a; 服务注册&#xff1a;服务提供者需要把自己的信息注册到eureka&#xff0c;由eureka来保存这些信息&#xff0c;比如服务名称、…...

kafka详解一

kafka详解一 1、消息引擎背景 根据维基百科的定义&#xff0c;消息引擎系统是一组规范。企业利用这组规范在不同系统之间传递语义准确的消息&#xff0c;实现松耦合的异步式数据传递. 即&#xff1a;系统 A 发送消息给消息引擎系统&#xff0c;系统 B 从消息引擎系统中读取 A…...

Flutter yuv 转 rgb

1、引用yuv_converter库 yuv_converter: ^0.0.1 2、导入头文件&#xff1a; import package:yuv_converter/yuv_converter.dart;3、yuv转rgb YuvConverter.yuv420NV21ToRgba8888(yuvRawData, 512, 512) 根据yuv格式选择不同的api。 举个例子&#xff1a; void initState() …...

MySQL——子查询

2023.9.8 相关学习笔记&#xff1a; #子查询 /* 含义&#xff1a; 出现在其他语句中的select语句&#xff0c;称为子查询或内查询 外部的查询语句&#xff0c;称为主查询或外查询分类&#xff1a; 按子查询出现的位置&#xff1a;select后面&#xff1a;仅仅支持标量子查询fro…...

Java学习笔记---多态

面向对象三大特征之一&#xff08;继承&#xff0c;封装&#xff0c;多态&#xff09; 多态的应用场景&#xff1a;根据传递对象的不同&#xff0c;调用不同的show方法 一、多态的定义 同类型的对象&#xff0c;表现出的不同形态&#xff08;对象的多种形态&#xff09; 二…...

2023-09-10 LeetCode每日一题(课程表 II)

2023-09-10每日一题 一、题目编号 210. 课程表 II二、题目链接 点击跳转到题目位置 三、题目描述 现在你总共有 numCourses 门课需要选&#xff0c;记为 0 到 numCourses - 1。给你一个数组 prerequisites &#xff0c;其中 prerequisites[i] [ai, bi] &#xff0c;表示在…...

合并区间【贪心算法】

合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 class Solution {public int[][] merge(int[…...

2023,软件测试人的未来在哪里?

2023年&#xff0c;IT行业出现空前的萧条&#xff0c;首先是年初一开始各大厂像着了魔似的不约而同的纷纷裁员、降薪、奖金包缩水&#xff0c;随之而来的是需求萎缩&#xff0c;HC减少或封锁等等。 而有幸未被列入裁员名单的在职人员&#xff0c;庆幸之余也心有余悸&#xff0…...

Python中的Numpy向量计算(R与Python系列第三篇)

目录 一、什么是Numpy? 二、如何导入NumPy? 三、生成NumPy数组 3.1利用序列生成 3.2使用特定函数生成NumPy数组 &#xff08;1&#xff09;使用np.arange() &#xff08;2&#xff09;使用np.linspace() 四、NumPy数组的其他常用函数 &#xff08;1&#xff09;np.z…...

LeetCode刷题笔记【27】:贪心算法专题-5(无重叠区间、划分字母区间、合并区间)

文章目录 前置知识435. 无重叠区间题目描述参考<452. 用最少数量的箭引爆气球>, 间接求解直接求"重叠区间数量" 763.划分字母区间题目描述贪心 - 建立"最后一个当前字母"数组优化marker创建的过程 56. 合并区间题目描述解题思路代码① 如果有重合就合…...

nvidia-smi 命令详解

nvidia-smi 命令详解 1. nvidia-smi 面板解析2. 显存与GPU的区别 Reference: nvidia-smi命令详解 相关文章&#xff1a; nvidia-smi nvcc -V 及 CUDA、cuDNN 安装 nvidia-smi(NVIDIA System Management Interface) 是一种命令行实用程序&#xff0c;用于监控和管理 NVIDIA G…...

fork()函数的返回值

在程序中&#xff0c;int pd fork() 是一个典型的 fork() 调用。fork() 函数会创建一个新的进程&#xff0c;然后在父进程中返回子进程的进程ID&#xff08;PID&#xff09;&#xff0c;在子进程中返回0。所以 pd 的值会根据当前进程是父进程还是子进程而有所不同&#xff1a;…...

Stable Diffusion WebUI挂VPN不能跑图解决办法(Windows)

如何解决SD在打开VPN的状态不能运行的问题 在我们开VPN的时候会出现无法生成图片&#xff0c;也无法做其他任何事&#xff0c;这个时候是不是很着急呢&#xff1f; 别急&#xff0c;我这里会说明如何解决。 就像这样&#xff0c;运行半天生成不了图&#xff0c;有时还会出现…...

Android的本地数据

何为本地&#xff0c;即写完之后除非手动修改&#xff0c;否像嘎了一样在那固定死了 有些需求可能也会要求我们去写死数据&#xff0c;因为这需求是一成不变的&#xff0c;那么你通常会用什么方法写死呢&#xff1f; 1. 本地存储-SharedPreferences 此方法可以长时间保存于手…...

android NDK 开发包,网盘下载,不限速

记录下ndk 开发包的地址&#xff0c;分享给大家。 另外有Android studio的下载包&#xff0c; 在另一篇文章 链接&#xff1a;http://t.csdn.cn/JSr9x Android Studio.exe 下载 2023 最新更新&#xff0c;网盘下载_hsj-obj的博客-CSDN博客 主要是19-25&#xff0c;其他的没有…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...