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的记录总结。

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

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

相关文章

选择合适的帧率和分辨率:优化RTSP流视频抓取(java)

引言 在实时视频流应用中&#xff0c;选择适当的帧率和分辨率对于确保视频流的顺畅播放和图像质量至关重要。本文将向您介绍如何使用Java和JavaCV库中的FFmpegFrameGrabber来从RTSP流中抓取图像&#xff0c;并在抓取时设置帧率和分辨率。 一、配置开发环境 首先&#xff0c;…

mysql之DML的select分组排序

目录 一、创建表employee和department表 1.创建department表 2.创建employee表 3.给employee表格和department表格建立外键 4.给department插入数据 5.给employee表插入数据 6.删除名字为那个的数据 二、分组查询和排序查询&#xff0c;以及对数据的处理&#xff08;av…

悲观锁和乐观锁、缓存

悲观锁&#xff1a; 悲观锁的实现通常依赖于数据库提供的机制&#xff0c;在整个处理的过程中数据处于锁定状态&#xff0c;session的load方法有一个重载方法&#xff0c;该重载方法的第三个参数可以设置锁模式&#xff0c;load(object.class , int id,LockMode.?)&#xff0…

OpenCV实现图像的混合

原理 这其实也是加法&#xff0c;但是不同的是两幅图像的权重不同&#xff0c;这就会给人一种混合或者透明的感觉。 图像混合的计算公式如下: g(x)(1-a)f0(x) af1(x) 通过修改α的值(0→1) &#xff0c;可以实现非常炫酷的混合。 现在我们把两幅图混合在一起。 第一幅图…

第6篇 vue的打包工具webpack

一 webpack 1.1 webpack的作用 webpack是一个打包工具&#xff0c;可以把多个静态资源文件打包成一个文件。如图所示&#xff1a; 1.2 版本依赖对照关系 PS E:\vue-project\vue-demo0902\wp-demo> npm -v 6.4.1 PS E:\vue-project\vue-demo0902\wp-demo> node -v v10.…

Redis使用原生命令搭建集群

1.Redis版本及下载 找到安装的redis版本&#xff0c;redis3.0以上版本才支持集群 下载对应的版本 2.安装redis集群 解压上传编译 [hadoophost152 opensource]$ tar -xvf redis-3.2.11.tar.gz [hadoophost152 opensource]$ cd redis-3.2.11/ [hadoophost152 redis-3.2.11]$ ma…

从零开始的PICO教程(4)--- UI界面绘制与响应事件

从零开始的PICO教程&#xff08;4&#xff09;— UI界面绘制与响应事件 文章目录 从零开始的PICO教程&#xff08;4&#xff09;--- UI界面绘制与响应事件一、前言1、大纲2、教程示例 二、具体步骤1、PICO VR环境配置2、XR的UI Canvas画布创建与调整&#xff08;1&#xff09;C…

用滑动条做调色板---cv2.getTrackbarPos(),cv2.creatTrackbar()

滑动轨迹栏作调色板 cv.createTrackbar(‘R’, ‘image’, 0, 255, nothing) 参数&#xff1a;哪个滑动轨迹栏&#xff0c;哪个窗口&#xff0c;最小值&#xff0c;最大值&#xff0c;回调函数 cv.getTrackbarPos(‘R’, ‘image’) 参数&#xff1a;轨迹栏名&#xff0c;窗口…

【Matlab】Matlab实现数据的动态显示方法

Matlab实现数据的动态显示方法 主要为大家详细介绍了Matlab使用Plot函数实现数据动态显示方法&#xff0c;具有一定的参考价值&#xff0c;感兴趣的小伙伴们可 以参考一下 对于真实系统或者仿真平台&#xff0c;数据是增量式的产生的。Matlab除了强大的矩阵运算外&#xff0c;还…

设计模式-单例模式(Singleton)

文章目录 前言一、单例模式的概念二、单例模式的实现三、单例模式的应用场景四、单例模式优缺点优点&#xff1a;缺点&#xff1a;总结 前言 单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供一…

CSS 斜条纹进度条

效果&#xff1a; 代码&#xff1a; html: <div class"active-line flex"><!-- lineWidth&#xff1a;灰色背景 --><div class"bg-line"><div v-for"n in 30" class"gray"></div></div><div…

win10环境安装使用docker-maxwell

目的&#xff1a;maxwell可以监控mysql数据变化&#xff0c;并同步到kafka、mq或tcp等。 maxwell和canal区别&#xff1a; maxwell更轻量&#xff0c;canal把表结构也输出了 docker bootstrap可导出历史数据&#xff0c;canal不能 环境 &#xff1a;win10&#xff0c;mysql5…

PYTHON(一)——认识python、基础知识

一、为什么要学习python&#xff1f; Python 被认为是人工智能、机器学习的首选语言&#xff0c;可以说是全世界最流行通用范围最广的语言&#xff0c;几乎可以完成所有的任务&#xff0c;像设计游戏、建网站、造机器人甚至人工智能等都广泛使用Python。 二、输出&#xff08;…

pdf文件签名的问题解决

今天解决冲突的jar&#xff0c;结果出现下面的问题 java.lang.IllegalAccessError: tried to access method org.bouncycastle.asn1.DERNull.<init>()V from class com.itextpdf.text.pdf.security.PdfPKCS7at com.itextpdf.text.pdf.security.PdfPKCS7.getEncodedPKCS7…

机器学习——K最近邻算法(KNN)

机器学习——K最近邻算法&#xff08;KNN&#xff09; 文章目录 前言一、原理二、距离度量方法2.1. 欧氏距离2.2. 曼哈顿距离2.3. 闵可夫斯基距离2.4. 余弦相似度2.5. 切比雪夫距离2.6. 马哈拉诺比斯距离2.7. 汉明距离 三、在MD编辑器中输入数学公式&#xff08;额外&#xff0…

门面设计模式

github&#xff1a;GitHub - QiuliangLee/pattern: 设计模式 1 什么是门面设计模式 门面设计模式是一种软件设计模式&#xff0c;也被称为外观&#xff08;Facade&#xff09;模式。它提供了一个简单的接口&#xff0c;让客户端能够访问复杂系统中的一组接口。通过门面模式&a…

企业架构LNMP学习笔记15

客户端缓存&#xff1a; B/S架构里&#xff0c;Browser是浏览器&#xff0c;就是客户端。 客户端缓存告知浏览器获取服务段的信息是在某个区间时间段是有效的。 每次请求从服务器拿一遍数据&#xff0c;数据没有变化&#xff0c;影响带宽&#xff0c;影响时间。刷新又要去加载…

Java中快速排序的优化技巧:随机取样、三数取中和插入排序

目录 快速排序基础 优化1&#xff1a;随机取样 优化2&#xff1a;三数取中 优化3&#xff1a;插入排序 总结&#xff1a; 快速排序&#xff08;Quick Sort&#xff09;是一种高效的排序算法&#xff0c;它的平均时间复杂度为O(n log n)。然而&#xff0c;在某些情况下&…

rust中的reborrow和NLL

reborrow 我们看下面这段代码 fn main() {let mut num 123;let ref1 &mut num; // 可变引用add(ref1); // 传递给 add 函数println!("{}", ref1); // 再次使用ref1 }fn add(num: &mut i32) {println!("{}", *num); }我们…

机器学习——生成分类数据的坐标系边界需要用到的技术方法

0、前言&#xff1a; 如果遇到一种应用场景需要将x轴数据和y轴数据所有点映射到坐标系中&#xff0c;需要得到坐标系中x和y映射的坐标点&#xff0c;就要用到meshgrid把x和y映射到坐标系中&#xff0c;然后把得到的结果用ravel把结果转成一维的。用np.c_()把x数据和y数据堆叠在…