数据结构:反射

基本概念

反射中的四个类

Class类

Java文件在被编译之后,生成了.class文件,JVM此时解读.class文件,将其解析为java.lang.Class

对象,在程序运行时每个java文件就最终变成了Class类对象的一个实例。通过反射机制应用这个

实例就可以获得甚至添加这个类的属性和动作。

方法

获得类相关方法

方法

用途

getClassLoader()

获得类的加载器

getDeclaredClasses()

返回一个数组,数组中包含该类中所有类和接口类的对象(包括私有的)

forName(String className)

根据类名返回类的对象

newInstance()

创建类的实例

getName()

获得类的完整路径的名字

 获得类属性的方法

方法

用途

getField(String name)

获得某个公有的属性对象

getFields()

获得所有公有的属性对象

getDeclaredField(String name)

获得某个属性对象

getDeclaredFields()

获得所有属性对象

获得类中构造器相关的方法

方法

用途

getConstructor(Class...<?> parameterTypes)

获得该类中与参数类型匹配的公有构造方法

getConstructors()

获得该类的所有公有构造方法

getDeclaredConstructor(Class...<?> parameterTypes)

获得该类中与参数类型匹配的构造方法

getDeclaredConstructors()

获得该类所有构造方法

获得类中方法相关的方法 

方法

用途

getMethod(String name, Class...<?> parameterTypes)

获得该类某个公有的方法

getMethods()

获得该类所有公有的方法

getDeclaredMethod(String name, Class...<?> parameterTypes)

获得该类某个方法

getDeclaredMethods()

获得该类所有方法

加了Declared就可以获得不只是公有的对象,还能获得私有的等等


获取Class对象的三种方式

1.使用Class.forName("类的全路径名")

2.使用.class方法

3.使用类对象的getClass()方法

class Student {//私有属性nameprivate String name = "bit";//公有属性agepublic int age = 18;//不带参数的构造方法public Student(){System.out.println("Student()");}private Student(String name,int age) {this.name = name;this.age = age;System.out.println("Student(String,name)");}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}
}
public class Test {/*Class对象 只有一个*/public static void main(String[] args) {Class<?> c1 = null;try {c1 = Class.forName("demo1.Student");} catch (ClassNotFoundException e) {e.printStackTrace();}Class<?> c2 = Student.class;Student student = new Student();Class<?> c3 = student.getClass();System.out.println(c1 == c2);System.out.println(c1 == c3);}
}


反射的使用

接下来我们开始使用反射,我们依旧反射上面的Student类,把反射的逻辑写到另外的类当中进行理解

创建对象

public class ReflectClassDemo {public static void reflectNewInstance() {Class<?> classStudent = null;try {classStudent = Class.forName("demo1.Student");Student student = (Student)classStudent.newInstance();System.out.println(student);}catch (ClassNotFoundException e) {e.printStackTrace();} catch (InstantiationException e) {throw new RuntimeException(e);//newInstance 是受查异常,要加多这一行进行排查} catch (IllegalAccessException e) {throw new RuntimeException(e);}}

 

反射私有的构造方法,并根据构造方法修改类的私有变量

    public static void reflectPrivateConstructor() {Class<?> classStudent = null;try {classStudent = Class.forName("demo1.Student");//获得构造方法Constructor<?> constructor = classStudent.getDeclaredConstructor(String.class,int.class);//根据Student类的构造方法来修改name和age变量Student student = (Student)constructor.newInstance("xiaoming",15);System.out.println(student);}catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {throw new RuntimeException(e);//newInstance 是受查异常,要加多这两行进行排查} catch (InvocationTargetException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}

Constructor<?> constructor = classStudent.getDeclaredConstructor(String.class,int.class); 

在这一行中我们要访问Student私有的成员变量,但是程序不知道我们要这么干就直接阻拦报错,所以我们需要写下面这行代码告诉系统我们确实要这么干。

constructor.setAccessible(true);

反射私有属性(不用构造方法直接修改私有属性的值)

    public static void reflectPrivateField() {Class<?> classStudent = null;try {classStudent = Class.forName("demo1.Student");Field field = classStudent.getDeclaredField("name");field.setAccessible(true);Student student = (Student)classStudent.newInstance();field.set(student,"caocao");System.out.println(student);}catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchFieldException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);}}

反射私有方法

    public static void reflectPrivateMethod() {Class<?> classStudent = null;try {classStudent = Class.forName("demo1.Student");Method method = classStudent.getDeclaredMethod("function",String.class);method.setAccessible(true);Student student = (Student)classStudent.newInstance();method.invoke(student,"我是一个反射的参数!");}catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {throw new RuntimeException(e);} catch (InstantiationException e) {throw new RuntimeException(e);} catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (InvocationTargetException e) {throw new RuntimeException(e);}

总结 

优点:

1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法 2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力

3. 反射已经运用在了很多流行框架如:  Struts HibernateSpring 等等。

缺点:

1. 使用反射会有效率问题。会导致程序效率降低。具体参考这里:  大家都说 Java 反射效率低,你知道原因在哪里么_慕课手记 2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。

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

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

相关文章

C# 异步日志记录类,方便下次使用,不用重复造轮子

先定义接口类&#xff1a; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 异常 {internal interface ILog{Task WriteErrorLog(string message);Task WriteInfoLog(string message);Task W…

MySQL索引下推:提升数据库性能的关键优化技术

文章目录 前言索引下推原理MySQL 基础架构传统查询过程ICP 查询过程 使用场景限制参数配置索引下推开启状态查询索引下推开启和关闭 一些问题只有联合索引才能使用索引下推&#xff1f;下面的查询为什么不走索引下推 参考 前言 大家好&#xff0c;我是 Lorin &#xff0c;今天…

C语言从文件 D://test.txt 读取字符串,将字符串中所有的大写字符改为小写字母并写回到源文件中

完整代码&#xff1a; /*从文件 D://test.txt 读取字符串&#xff0c;将字符串中所有的大写字母改为小写字母并写回 到源文件中*/ #include<stdio.h>//将字符串中所有的大写字母改为小写字母 void func(char *buff){while (*buff!\0){if (*buff>A&&*buff<…

java基础-数据类型

1、变量 变量就是申请内存来存储值。也就是说&#xff0c;当创建变量的时候&#xff0c;需要在内存中申请空间。 内存管理系统根据变量的类型为变量分配存储空间&#xff0c;分配的空间只能用来储存该类型数据。 因此&#xff0c;通过定义不同类型的变量&#xff0c;可以在内…

【C#学习】button:只显示图片

第一步&#xff1a;设置按钮背景图片&#xff0c;并且图片随按钮大小变化 第二步&#xff1a;设置按钮使之只显示图片 button1.FlatStyle FlatStyle.Flat;//stylebutton1.ForeColor Color.Transparent;//前景button1.BackColor Color.Transparent;//去背景button1.FlatAppe…

破解tomcat密码并上传webshell

tomcat基础认证爆破 暴力破解 进入vulnhub的tomcat8目录&#xff0c;启动环境 由于tomcat密码默认最大尝试错误次数为5次&#xff0c;需要修改server.xml&#xff0c;修改下面字段 failureCount"10000000000" lockOutTime"0"tomcat默认界面&#xff0c;…

MATLAB仿真通信系统的眼图

eyediagram eyediagram(complex(used_i,used_q),1100)

Spring Framework中的依赖注入:构造器注入 vs. Setter注入

前言 构造器注入和Setter注入是依赖注入&#xff08;Dependency Injection&#xff0c;DI&#xff09;中两种常见的方式&#xff0c;用于向一个对象注入其所依赖的其他对象或数值。这两种注入方式有各自的特点和用途。 构造器注入&#xff08;Constructor Injection&#xff…

【LeetCode刷题-滑动窗口】-- 643.子数组最大平均数I

643.子数组最大平均数I 方法&#xff1a;滑动窗口 class Solution {public double findMaxAverage(int[] nums, int k) {int n nums.length;int winSum 0;//先求出第一个窗口的和for(int i 0;i<k;i){winSum nums[i];}//通过遍历求出除了第一窗口的和int res winSum;fo…

抖斗音_快块手直播间获客助手+采集脚本+引流软件功能介绍

软件功能&#xff1a; 支持同时采集多个直播间&#xff0c;弹幕&#xff0c;关*注&#xff0c;礼*物&#xff0c;进直播间&#xff0c;部分用户手*号,粉*丝团采集 不支持采集匿*名直播间 设备需求&#xff1a; 电脑&#xff08;win10系统&#xff09; 文章分享者&#xff1…

28 nacos多环境配置共享

1.3.配置共享 其实微服务启动时&#xff0c;会去nacos读取多个配置文件&#xff0c;例如&#xff1a; [spring.application.name]-[spring.profiles.active].yaml&#xff0c;例如&#xff1a;userservice-dev.yaml [spring.application.name].yaml&#xff0c;例如&#xff…

双十一电视盒子哪个牌子好?测评工作室整理口碑电视盒子排名

在挑选电视盒子的时候&#xff0c;新手朋友们不知道从何下手&#xff0c;最近很多粉丝评论想要我们分享双11电视盒子推荐&#xff0c;于是我们根据用户的评价整理了目前口碑最好的电视盒子排名&#xff0c;给不懂电视盒子哪个牌子好的朋友们做个参考。 TOP 1、泰捷WEBOX WE40S电…