数据结构-----反射

文章目录

  • 反射
    • 1.定义
    • 2 用途(了解)
    • 3 反射基本信息
    • 4 反射相关的类(重要)
      • 4.1 Class类(反射机制的起源 )
        • 4.1.1 Class类中的相关方法(方法的使用方法在后边的示例当中)
      • 4.2 反射示例
        • 4.2.1 获得Class对象的三种方式
        • 4.2.2 反射的使用
    • 5、反射优点和缺点
    • 6 重点总结

反射

1.定义

Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制

2 用途(了解)

  1. 在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法
  2. 反射最重要的用途就是开发各种通用框架,比如在spring中,我们将所有的类Bean交给spring容器管理,无论是XML配置Bean还是注解配置,当我们从容器中获取Bean来依赖注入时,容器会读取配置,而配置中给的就是类的信息,spring根据这些信息,需要创建那些Bean,spring就动态的创建这些类。

3 反射基本信息

Java程序中许多对象在运行时会出现两种类型:运行时类型(RTTI)编译时类型,例如

Person p = new Student();

这句代码中p在编译时类型为Person,运行时类型为Student。程序需要在运行时发现对象和类的真实信息。而通过使用反射程序就能判断出该对象和类属于哪些类。

4 反射相关的类(重要)

在这里插入图片描述

4.1 Class类(反射机制的起源 )

Class帮助文档代表类的实体,在运行的Java应用程序中表示类和接口 .

Java文件被编译后,生成了.class文件,JVM此时就要去解读.class文件 ,被编译后的Java文件.class也被JVM解析为一个对象,这个对象就是java.lang.Class .这样当程序在运行时,每个java文件就最终变成了Class类对象的一个实例。我们通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类 .

4.1.1 Class类中的相关方法(方法的使用方法在后边的示例当中)
  • (重要)常用获得类相关的方法
    在这里插入图片描述
  • (重要)常用获得类中属性相关的方法(以下方法返回值为Field)
    在这里插入图片描述
  • (了解)获得类中注解相关的方法
    在这里插入图片描述
  • (重要)获得类中构造器相关的方法(以下方法返回值为Constructor)
    在这里插入图片描述
  • (重要)获得类中方法相关的方法(以下方法返回值为Method)
    在这里插入图片描述

4.2 反射示例

4.2.1 获得Class对象的三种方式

在反射之前,我们需要做的第一步就是先拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的,即:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们就可以修改部分类型信息。

创建一个进行反射的类:

class Student {
    //私有属性
    private String name = "bit";
    //公有属性
    public int age = 18;

    //不带参数的构造方法
    public Student() {
        System.out.println("dome1.Student()");
    }

    //带参数的构造方法
    private Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("dome1.Student(String,name)");
    }

    //私有的不带参数的构造方法
    private void eat() {
        System.out.println("i am eat");
    }


    //公有的不带参数的构造方法
    public void sleep() {
        System.out.println("i am pig");
    }

    //公有的带参数的构造方法
    private void function(String str) {
        System.out.println(str);
    }

    @Override
    public String toString() {
        return "dome1.Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

第一种,使用 Class.forName(“类的全路径名”); 静态方法。
前提:已明确类的全路径名。

//        1、通过 Class 对象的 forName() 静态方法来获取,用的最多,
//        但可能抛出 ClassNotFoundException 异常
        Class<?> c1 = null;
        try {
            c1 = Class.forName("dome1.Student");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

第二种,使用 .class 方法。
说明:仅适合在编译前就已经明确要操作的 Class

//        2.直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
//        这说明任何一个类都有一个隐含的静态成员变量 class

        Class c2 = Student.class;

第三种,使用类对象的 getClass() 方法

//        3.通过getClass获取Class对象

        Student s1 = new Student();
        Class c3 = s1.getClass();

这三个对象是不是同一个对象:

        //一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的
        //c1,c2,c3进行 equals 比较,发现都是true
        System.out.println(c1 == c2);
        System.out.println(c1 == c3);
        System.out.println(c2 == c3);
运行结果:
true
true
true

说明,class对象只有一个,建议使用方法一和方法二来获取class对象,第三个方法需要额外创建一个Student对象不推荐。

4.2.2 反射的使用

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

注意:所有和反射相关的包都在 import java.lang.reflect 包下面。

  1. 使用反射创建对象
	public static void reflectNewInstance() {
        Class<?> classStudent = null;
        try {
            classStudent = Class.forName("demo1.Student");
            Student student1 = (Student) classStudent.newInstance();
            System.out.println(student1);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
  1. 通过反射使用私有的构造方法创建对象
    // 反射私有的构造方法 屏蔽内容为获得公有的构造方法
    public static void reflectPrivateConstructor() {
        Class<?> classStudent = null;
        try {
            classStudent = Class.forName("demo1.Student");
            //注意参数
            Constructor<?> studentDeclaredConstructor = classStudent.getDeclaredConstructor(String.class, int.class);
            //如果是访问私有的,必须设置为true后可修改访问权限
            studentDeclaredConstructor.setAccessible(true);//暴力反射
            Student student1 = (Student) studentDeclaredConstructor.newInstance("张三", 18);
            System.out.println("获得私有构造哈数且修改姓名和年龄:"+student1);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

代码运行结果:
在这里插入图片描述

  1. 通过反射修改对象的私有属性
   // 反射私有属性
    public static void reflectPrivateField() {
        Class<?> classStudent = null;
        try {
            classStudent = Class.forName("demo1.Student");
            Field name = classStudent.getDeclaredField("name");

            name.setAccessible(true);
           Student student1 = (Student) classStudent.newInstance();//创建一个对象,修改该对象的name字段
            //可以修改该属性的值
            name.set(student1,"xiaoming");

            System.out.println("反射私有属性修改了name:"+ student1);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

    }

在这里插入图片描述

  1. 通过反射调用对象的私有方法
    // 反射私有方法
    public static void reflectPrivateMethod() {
        Class<?> classStudent = null;

        try {
            classStudent = Class.forName("demo1.Student");
            //获取类私有的带参数的构造方法
            Method studentDeclaredMethod = classStudent.getDeclaredMethod("function", String.class);
            //设置为true后可修改访问权限
            studentDeclaredMethod.setAccessible(true);
            Student student1 = (Student) classStudent.newInstance();//创建一个对象

            //调用方法
            studentDeclaredMethod.invoke(student1, "我是给私有的function函数传的参数");

        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } 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);
        }
    }

在这里插入图片描述

5、反射优点和缺点

优点:

  1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法
  2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力
  3. 反射已经运用在了很多流行框架如:Struts、Hibernate、Spring 等等。

缺点:

  1. 使用反射会有效率问题。会导致程序效率降低。
  2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。

6 重点总结

Java反射是Java编程语言的一个重要特性,它允许程序在运行时动态地获取类的信息、调用类的方法、访问类的属性等。Java反射的意义在于:

  1. 动态加载类:Java反射可以在运行时动态加载和实例化类,而不需要在编译时确定类的类型。这样可以实现灵活的类加载机制,使程序更加可扩展和灵活。

  2. 动态调用方法:通过Java反射,可以在运行时动态调用类的方法,无需在编译时确定方法的名称和参数类型。这样可以实现动态调用和扩展,使程序更加灵活和可配置。

  3. 访问私有属性和方法:Java反射可以访问类的私有属性和方法,即使它们被声明为私有的。这样可以实现对类的更深层次的操作和控制。

  4. 框架和工具的设计:许多Java框架和工具都使用了反射机制,如Spring框架、JUnit测试框架等。通过反射,这些框架和工具可以实现自动化配置、自动化测试等功能,提高了开发效率和代码的灵活性。

总的来说,Java反射提供了一种强大的机制,可以使程序更加灵活、可扩展和动态。但是需要注意的是,反射的使用可能会降低程序的性能和安全性,因此在使用反射时需要谨慎考虑。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

七、基于FreeRTOSSTM32移植MQTT

1、移植环境 (1)Keil MDK: V5.38.0.0 (2)STM32CubeMX: V6.8.1 (3)MCU: STM32F407ZGT6 (4)已移植好FreeRTOS和调试好串口的项目。 FreeRTOS移植参考博客&#xff1a;示例1&#xff1a;FreeRTOS移植详解_基于HAL库工程_hal库移植rtos-CSDN博客mqttclient源码&#xff1a;htt…

如何自学python

Python是一种高级编程语言,它具有简单易学、可读性强、可移植性好、功能丰富等优点,因此在许多领域都被广泛使用,如科学计算、数据分析、人工智能、Web开发、游戏开发等等。 Python具有丰富的标准库和第三方库,可以帮助程序员快速开发功能强大的应用程序。同时,Python也具…

免费下载全网视频系列:一键下载央视视频

之前分享过全网视频下载工具下载视频不求人&#xff0c;免费下载全网视频&#xff0c;今天再分享几个下载央视视频的工具。 第一个是央视频4k下载器&#xff0c;比如下载这个视频https://www.yangshipin.cn/#/video/home?vidv0000313oqb&#xff0c;打开工具在命令行输入 v00…

Vue.js+SpringBoot开发在线课程教学系统

目录 一、摘要1.1 系统介绍1.2 项目录屏 二、研究内容2.1 课程类型管理模块2.2 课程管理模块2.3 课时管理模块2.4 课程交互模块2.5 系统基础模块 三、系统设计3.1 用例设计3.2 数据库设计 四、系统展示4.1 管理后台4.2 用户网页 五、样例代码5.1 新增课程类型5.2 网站登录5.3 课…

[技巧]Arcgis之图斑四至范围批量计算

ArcGIS图层&#xff08;点、线、面三类图形&#xff09;四至范围计算 例外一篇介绍&#xff1a;[技巧]Arcgis之图斑四至点批量计算 说明&#xff1a;如下图画出来的框&#xff08;范围标记不是很准&#xff09; &#xff0c;图斑的x最大和x最小&#xff0c;y最大&#xff0c;…

社区店经营实战策略:如何打造火爆生意并持续盈利?

在竞争激烈的商业环境中&#xff0c;经营一家成功的社区店需要一套全面而有效的策略。作为一名开鲜奶吧5年的创业者&#xff0c;我将分享一些关键的经营策略&#xff0c;帮助你打造火爆生意并实现持续盈利。 1、 市场调研&#xff1a; 在开店之前&#xff0c;深入了解你所在社…

内存占用构造方法

#使用虚拟内存构造内存消耗 mkdir /tmp/memory mount -t tmpfs -o size5G tmpfs /tmp/memory dd if/dev/zero of/tmp/memory/block #释放消耗的虚拟内存 rm -rf /tmp/memory/block umount /tmp/memory rmdir /tmp/memory #内存占用可直接在/dev/shm目录下写文件

#WEB前端(表单)

1.实验&#xff1a; form、input、label 登录界面&#xff0c;表单填写界面 2.IDE&#xff1a;VSCODE 3.记录&#xff1a; 4.代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name&q…

【Linux】基本指令(中)

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:Linux ⚙️操作环境:Xshell (操作系统:CentOS 7.9 64位) man指令 语法:man [选项] 命令 功能:Linux的命令有很多参数&#xff0c;我们无法全部记忆的话&#xff0c;就可以通过man指令查看联机手册获取帮助。…

递归与回溯2

一&#xff1a;递归分治 什么是递归&#xff1f; 函数自己调用自己通过函数体来进行循环以自相似的方法重复进行的过程 递归的过程&#xff1a;先自顶向下找到递归出口&#xff0c;在自底向上回到最初的递归位置 推导路径未知的题目只能用递归不能用循环 比如求多叉树的节点&…

SpringBoot+Jwt+Redis

大致流程&#xff1a; 参照&#xff1a; 史上最全面的基于JWT token登陆验证_完整的基于jwt的登陆认证-CSDN博客 springboot整合JWTRedis_springboot jwt redis-CSDN博客

【QT+QGIS跨平台编译】之六十二:【QGIS_CORE跨平台编译】—【错误处理:未定义类型QgsPolymorphicRelation】

文章目录 一、未定义类型QgsPolymorphicRelation二、解决办法一、未定义类型QgsPolymorphicRelation 报错信息: 错误原因为,使用了未定义类型 QgsPolymorphicRelation 二、解决办法 QgsRelation.h文件中 ①注释第36行: //class QgsPolymorphicRelation;②注释第414行: …

构建大语言模型的四个主要阶段

大规模语言模型的发展历程虽然只有短短不到五年的时间&#xff0c;但是发展速度相当惊人&#xff0c;国内外有超过百种大模型相继发布。中国人民大学赵鑫教授团队在文献按照时间线给出 2019 年至 2023 年比较有影响力并且模型参数量超过 100 亿的大规模语言模型。大规模语言模型…

BUGKU 本地管理员

打开环境&#xff0c;先F12查看看到一串代码。Base64解码一下&#xff0c;得到的应该是密码&#xff0c;然后输入admin | test123试一下 使用BP抓包&#xff0c;修改XFF&#xff0c;得到flag

Vue开发实例(六)实现左侧菜单导航

左侧菜单导航 一、一级菜单二、二级菜单三、三级菜单1、加入相关事件 四、菜单点击跳转1. 创建新页面2. 配置路由3. 菜单中加入路由配置4、处理默认的Main窗口为空的情况 五、动态左侧菜单导航1、动态实现一级菜单2、动态实现二级菜单 一、一级菜单 在之前的Aside.vue中去实现…

php儿童服装销售管理系统计算机毕业设计项目包运行调试

php mysql儿童服装销售网 功能&#xff1a;前台后台 前台&#xff1a; 1.服装资讯 文章标题列表 详情 2.服装选购中心 分页查看图文列表 详情 3.用户注册 登陆 退出 4.服装加入收藏 5.加入购物车 6.对服装进行评论 会员中心&#xff1a; 1.我的账户 查看 修改 2.我的收藏 查看 …

文献阅读笔记《Spatial-temporal Forecasting for Regions without Observations》13页

目录 发行刊物 ABSTRACT 1 INTRODUCTION 2 RELATED WORK&#xff08;相关工作 2.1 Spatial-temporal Forecasting&#xff08;时空预测 2.2 Spatial-temporal Forecasting withIncomplete Data&#xff08;不完全数据的时空预测 2.3 Graph Contrastive Learning&#xf…

Vue2:路由的两种模式history模式和hash模式

一、情景说明 之前我们写的项目启动后&#xff0c;浏览器访问时&#xff0c;路径中会有个#/&#xff0c;会导致不够美观 因为一般的访问地址都是http://123.123.123.123/aaa/bbb这种形式 这一篇&#xff0c;就来解决这个问题 二、案例 1、hash模式 特点&#xff1a;#/后的…

【JavaEE进阶】 代理模式

文章目录 &#x1f343;前言&#x1f38b;什么叫代理模式&#x1f334;静态代理&#x1f38d;动态代理&#x1f6a9;JDK动态代理&#x1f6a9;CGLIB动态代理 ⭕总结 &#x1f343;前言 前面对Spring AOP的详细使用进行了介绍&#xff0c;这篇博客博主将详细讲解一下Spring AOP…

lottie加载带图片的json 预览

背景 产品看到一款app的动效很不错&#xff0c;让我去模仿实现。 第一步 获取apk中的静态资源 拿到这个app的apk后&#xff0c;直接使用压缩工具解压&#xff0c; assets文件夹就是静态资源的目录 静态资源里面有lottie 那么大部分的动效应该都是lottie实现的 网上找了很多…