反射(Reflection) --Java学习笔记

反射

  • 反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)

反射学什么?

学习获取类的信息、操作它们

  1. 反射第一步:加载类,获取类的字节码:Class对象
  2. 获取类的构造器:Constructor对象
  3. 获取类的成员变量:Field对象
  4. 获取类的成员方法:Method对象

全部认识完后,再看反射的应用场景

1、反射第一步:加载类,获取类的字节码:Class对象

获取Class对象的三种方式

  • Class c1=类名.class
  • 调用Class提供方法:  public static Class forName(String package)
  • Object提供的方法:  publicClass getClass();  Class c3=对象.getClass()

代码演示:

package com.zeyu.reflect;

public class Test1Class {
    public static void main(String[] args) throws Exception {
        Class c1 = Student.class;
        System.out.println(c1.getName());   //全类名
        System.out.println(c1.getSimpleName()); //简名:Student

        Class c2 = Class.forName("com.zeyu.reflect.Student");   //填全类名
        System.out.println(c1 == c2);   //拿到的是同一个对象

        Student s = new Student();  //创建类的实例
        Class c3 = s.getClass();    //调用getClass方法
        System.out.println(c3 == c2);   //拿到的依旧是同一个对象
    }
}

运行结果:

2、获取类的构造器:Constructor对象

Class提供了从类中获取构造器的方法

获取类构造器的作用:依然是初始化对象返回

代码演示:

package com.zeyu.reflect;

import org.junit.Test;

import java.lang.reflect.Constructor;

public class Test2Constructor {
    @Test
    public void testGetConstructors() {
        //1、反射第一步,必须先得到这个类的class对象
        Class c = Cat.class;
        //2、获取类的全部构造器
//        Constructor[] constructors = c.getConstructors();   //只能拿public类型的构造器
        Constructor[] constructors = c.getDeclaredConstructors();
        //3、遍历数组中的每一个构造器对象
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + "-->" + constructor.getParameterCount());
        }
    }

        @Test
        public void testGetConstructor() throws Exception {
            //1、反射第一步,必须先得到这个类的class对象
            Class c = Cat.class;
            //2、获取某一个构造器:无参构造器
//            Constructor constructor = c.getConstructor(); //只能拿public类型的构造器
            Constructor constructor = c.getDeclaredConstructor();   //存在就能拿到
            System.out.println(constructor.getName() + "-->" + constructor.getParameterCount());
            constructor.setAccessible(true);    //禁止检查访问权限
            Cat cat = (Cat) constructor.newInstance();  //调用构造器完成对象初始化
            System.out.println(cat);

            //获取有参构造器
            Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);
            System.out.println(constructor2.getName() + "-->" + constructor2.getParameterCount());
            constructor2.setAccessible(true);
            Object cat2 = constructor2.newInstance("黑猫警长", 3);  //初始化对象
            System.out.println(cat2);
        }
}

运行结果:

也可以用反射破坏单例设计模式

3、获取类的成员变量:Field对象

Class提供了从类中获取成员变量的方法

获取到成员变量的作用:依然是赋值、取值

代码演示:

package com.zeyu.reflect;

import org.junit.Test;

import java.lang.reflect.Field;

public class Test3Field {
    @Test
    public void testGetFields() throws Exception {
        //反射第一步,必须先拿到类的class对象
        Class c = Cat.class;
        //获取类的全部成员变量
        Field[] fields = c.getDeclaredFields();
        //遍历这个成员变量数组
        for (Field field : fields) {
            System.out.println(field.getName() + "--->" + field.getType());
        }

        //拿到某个成员变量
        Field fName = c.getDeclaredField("name");
        System.out.println(fName.getName() + "--->" + fName.getType());

        Field fAge = c.getDeclaredField("age");
        System.out.println(fAge.getName() + "--->" + fAge.getType());

        //赋值
        Cat cat = new Cat();
        fName.setAccessible(true);    //暴力访问
        fName.set(cat,"小橘");
        System.out.println(cat);

        //取值
        String name = (String) fName.get(cat);
        System.out.println(name);
    }
}

运行结果:

4、获取类的成员方法:Method对象

Class提供了从类中获取成员方法的API

成员方法的作用:依然是执行

代码演示:

package com.zeyu.reflect;

import org.junit.Test;

import java.lang.reflect.Method;

public class Test4Methods {
    @Test
    public void TestGetMethods() throws Exception {
        //1、反射第一步,先得到类的class对象
        Class c = Cat.class;
        //2、获取类的全部成员方法
        Method[] methods = c.getDeclaredMethods();
        //3、遍历这个数组的每个方法对象
        for (Method method : methods) {               //getParameterCount()统计形参个数
            System.out.println(method.getName() + "--->" + method.getParameterCount() + "--->"
            + method.getReturnType());
        }
        //4、获取某个方法对象
        Method run = c.getDeclaredMethod("run");
        System.out.println(run.getName() + "--->" + run.getParameterCount() + "--->"
                + run.getReturnType());

        Method eat = c.getDeclaredMethod("eat", String.class);
        System.out.println(eat.getName() + "--->" + eat.getParameterCount() + "--->"
                + eat.getReturnType());

        Cat cat = new Cat();
        run.setAccessible(true);    //禁止检查访问权限
        Object rs = run.invoke(cat);//调用无参run方法,用cat对象调用
        System.out.println(rs); //无返回值,返回结果为空

        eat.setAccessible(true);
        Object rs2 = (String) eat.invoke(cat, "鱼");
        System.out.println(rs2);
    }
}

运行结果:

反射的作用?

  • 基本作用:可以得到一个类的全部成分然后操作
  • 可以破坏封装性
  • 最重要的用途是:适合做lava的框架,基本上,丰流的框架都会基于反射设计出一些通用的功能

案例:使用反射做一个简易版的框架

需求:
对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去

实现步骤

  1. 定义一个方法,可以接收任意对象
  2. 每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量
  3. 遍历成员变量,然后提取成员变量在该对象中的具体值
  4. 把成员变量名、和其值,写出到文件中去即可

代码演示:

实现类:

package com.zeyu.reflect;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class ObjectFrame {
    //保存任意对象的字段和数据到文件中去
    public static void saveObject(Object obj) throws Exception {
        PrintStream ps = new PrintStream(new FileOutputStream("src\\com\\zeyu\\reflect\\data.txt",true));
        //obj是任意对象,到底有多少字段需要保存
        Class c = obj.getClass();
        String cname = c.getSimpleName();
        ps.println("------------------" + cname + "------------------");
        //从这个类中提取它的全部成员变量
        Field[] fields = c.getDeclaredFields();
        //遍历每个成员变量
        for (Field field : fields) {
            field.setAccessible(true);
            //拿到成员变量的名字
            String name = field.getName();
            //拿到这个成员变量在对象中的数据
            String value = field.get(obj) + "";
            ps.println(name + "=" + value);
        }
        ps.close();
    }
}

测试类:

package com.zeyu.reflect;

import org.junit.Test;

public class Teat5ObjectFrame {
    @Test
    public void testSave() throws Exception {
        Cat cat = new Cat("小橘",2);
        Student s = new Student("小明","男",22,172.8);

        ObjectFrame.saveObject(cat);
        ObjectFrame.saveObject(s);
    }
}

运行结果:

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

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

相关文章

SpringBoot集成Skywalking日志收集

在实际项目中,为了方便线上排查问题,尤其是微服务之间调用链路比较复杂的系统中,通过可视化日志的手段仍然是最直接也很方便的排查定位问题的手段,比如大家熟悉的ELK就是一种比较成熟的可视化日志展现方式,在skywalkin…

语音情感识别调研

语音情感识别调研 1、情绪识别综述2、语音情感识别算法3、语音特征提取4、相关项目1、用 LSTM、CNN、SVM、MLP 进行语音情感识别2、DST:基于Transformer的可变形语音情感识别模型3、语音情感基座模型emotion2vec4、IEEE ICME 2023论文|基于交互式注意力的…

康姿百德床垫官网价格公道,为你带来健康与舒适的睡眠享受

我们一生中有很长一段时间在睡眠度过,睡眠之于我们来说十分重要。良好的睡眠质量不仅能够帮助我们更好地恢复体力和精神,还能提高我们的生活质量。因此选择一款优质的床垫变得尤为重要。作为床垫行业的领导品牌,康姿百德床垫一直以提升人们睡…

stm32 之SPI通信协议

本文为大家介绍 SPI 通信协议的基础知识。 文章目录 前言一、SPI协议的概念二、SPI总线架构三、SPI通讯时序1. 起始,停止 信号2.CPOL(时钟极性)/CPHA(时钟相位) 四, I2C 总线 和SPI 总线比较相同点&#xf…

二叉树的前序遍历、中序遍历、后序遍历

二叉树的前序遍历、中序遍历、后序遍历 一、递归算法的三个要素二、144. 二叉树的前序遍历三、94. 二叉树的中序遍历四、145. 二叉树的后序遍历 一、递归算法的三个要素 1、确定递归函数的参数和返回值: 确定哪些参数是递归的过程中需要处理的,那么就在…

【单片机】PMS5003,PM2.5传感器数据读取处理

文章目录 传感器介绍数据处理解析pm2.5的代码帮助、问询 传感器介绍 PMS5003是一款基于激光散射原理的数字式通用颗粒物浓度传感器,可连续采集 并计算单位体积内空气中不同粒径的悬浮颗粒物个数,即颗粒物浓度分布,进而 换算成为质量浓度,并以通用数字接口形式输出。本传感器可…

LangChain-15 Manage Prompt Size 管理上下文大小,用Agent的方式询问问题,并去百科检索内容,总结后返回

背景描述 这一节内容比较复杂: 涉及到使用工具进行百科的检索(有现成的插件)有AgentExecutor来帮助我们执行后续由于上下文过大, 我们通过计算num_tokens,来控制我们的上下文 安装依赖 pip install --upgrade --qu…

SpringBoot整合RabbitMQ-应答模式

一、应答模式 RabbitMQ 中的消息应答模式主要包括两种:自动应答(Automatic Acknowledgement)和手动应答(Manual Acknowledgement)。(一般交换机发送消息,RabbitMQ只有在接收到消费者的确认后才…

常见性能测试工具对比

在性能测试工作中,我们常常会遇到好几个工具,但是每一个工具都有自己的优势,一时间不知道怎么选择。 今天我们就将性能测试常用的工具进行对比,这样大家在选择工具的时候心里就有底啦! 阿里云PTS 性能测试PTS&#xff…

基于springboot实现常州地方旅游管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现旅游管理系统演示 摘要 随着旅游业的迅速发展,传统的旅游信息查询方式,已经无法满足用户需求,因此,结合计算机技术的优势和普及,针对常州旅游,特开发了本基于Bootstrap的常州地方旅游管…

C++初阶:6.string类

string类 string不属于STL,早于STL出现 看文档 C非官网(建议用这个) C官网 文章目录 string类一.为什么学习string类?1.C语言中的字符串2. 两个面试题(暂不做讲解) 二.标准库中的string类1. string类(了解)2. string类的常用接口说明(注意下面我只讲解…

ONNX系列: ONNX模型修改

ONNX 模型修改 当我们熟悉了ONNX模型各个层级的结构后,我们便可以针对各个结构来对模型进行修改,从而使其更好的适配后端运行时或者特定硬件平台的编译器。对模型的修改通常可以概括为"增删改查"的操作。"增"是增加相应结构&#xf…

SAP 采购订单预制发票不让重复开立增强(包含:LMR1MF6S)<转载>

原文链接:https://blog.csdn.net/LH26988/article/details/136802631 之前博主有介绍过通过配置来控制不让采购发票重复开立,然是这个方式有点缺陷(跳转) 今天介绍,通过增强来彻底搞定这个问题的办法: 问题…

数组与链表:JavaScript中的数据结构选择

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

环境监测站升级选择ARM网关驱动精准数据采集

物联网技术的深入发展和环保需求的不断攀升,API调用网关在环境监测领域的应用正成为科技创新的重要推手。其中,集成了API调用功能的ARM工控机/网关,以其出色的计算性能、节能特性及高度稳定性,成功搭建起连接物理世界与数字世界的…

vue3移动端H5 瀑布流显示列表

以上效果 是之前发送的改进版 waterList <template><view class"pro-cons" v-if"data.length"><view class"cons-left"><template v-for"(item, index) in data"><template v-if"(index 1) % 2 1…

wangEditor 测试环境对,但是生产环境无法显示

package.json 文件版本 "wangeditor": "4.3.0"开发环境 new Editor(#${this.id});出来的数据 正式环境 new Editor(#${this.id});出来的数据 原因&#xff1a; vue.config 文件 打包策略的时候 const assetsCDN {css: [https://lf6-cdn-tos.bytecd…

【分析 GClog 的吞吐量和停顿时间、heapdump 内存泄漏分析】

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容GClog分析以优化吞吐量和停顿时间步骤1: 收集GClog步骤2: 分析GClog步骤3: 优化建议步骤4: 实施优化 Heapdump内存泄漏分析步骤1: 获取Heapdump步骤2: 分析Heapdump步骤3: 定位泄漏对象步骤4: 分析泄漏原因步骤5: 修复泄漏…

基于YOLOv8的摄像头下铁路工人安全作业检测系统

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文摘要&#xff1a;基于YOLOv8的铁路工人安全作业检测系统&#xff0c;属于小目标检测范畴&#xff0c;并阐述了整个数据制作和训练可视化过程&#xff0c; 博主简介 AI小怪兽&#xff0c;YOLO骨灰级玩家&#xff0c;1&#xff0…

物联网实战--驱动篇之(六)4G通讯(Air780E)

目录 一、4G模块简介 二、AIR780E驱动程序 三、AIR780使用注意事项 四、结合MQTT传输测试 一、4G模块简介 4G应该是我们日常生活最常见的一种互联网通讯方式了&#xff0c;每个智能手机都配置了&#xff0c;不过手机的4G跟我们物联网领域要用的4G有点区别。首先是物联网采用…