反射复习(java)

news2024/12/23 1:47:38

文章目录

  • 反射机制的作用
  • 反射机制的原理
    • 加载机制详细解释
  • 获取 Class 对象
  • 反射获取构造方法:获取 Class 对象里面 Constructor 对象
  • 反射获取成员变量:获取Class 对象里面的 Field 对象
  • 反射获取成员方法:获取 Class 对象里的 Method 对象
  • 其他常用 API

前言

反射非常重要,一定要掌握,我个人觉得不是很难,就是要注意各种方法里的参数是什么,然后还是那句话:最快的入门方式是看视频,建议先看完视频,再来看博客,这里我推荐 b 站韩顺平老师的视频

反射机制的作用

作用看不懂的话可以最后看

反射可以在不修改源码的情况下来控制程序符合 ocp 原则 :不修改源码,扩容功能


举个例子

现在有一个 main 类 和 Person 类,还有一个配置文件my.Properties,可以利用反射通过中间的 my.Properties 访问类中的东西

my.Properties

Classfullpath = com.mangfu.Person
field = name

Person

public class Person {
    public String name = "jack";
    public int age = 13;

    public Person() {};
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

}

Main

public class Main {
    public static void main(String[] args) throws Exception{

        //导入配置文件
        Properties properties = new Properties();
        properties.load(new FileInputStream("src/com/mangfu/my.Properties"));

        //通过配置文件获取 类的完整路径, 和类的属性名
        String classfullpath = properties.getProperty("Classfullpath");
        String field = properties.getProperty("field");

        //通过反射获取到 Person类的字节码对象,我们可以操作里面所有的东西
        Person person = new Person();
        Class clazz = Class.forName(classfullpath);

        //这里直接操作类里面的属性
        //本来是要 person.name 改成 person.age
        //现在直接在配置文件中的 name 改成 age就行了
        Field field1 = clazz.getField(field);
        System.out.println(field1.get(person));

    }
}

可以看见我们可以通过中间的 配置文件 无需修改源码,就能操作类中的信息




反射机制的原理

在这里插入图片描述

编译的时候会产生字节码文件,然后通过类加载器,进入加载阶段,会在堆区创建一个 Class 类的对象,当然这个Class对象里面的成员变量,构造器,构造方法等东西都是对象,然后 到 new Cat(),在 堆区创建 Cat 对象,该对象知道他属于哪个 Class 对象,我们可以通过反射得到这个 Class 对象,然后操作类中的所有东西

注意一个类只有一个 Class 对象



加载机制详细解释

类加载过程图
在这里插入图片描述


Loading(加载)

JVM 将 字节码文件 从 不同 的 数据源,转化为 二进制字节流,加载到内存中,生成一个代表该类的 Class 对象,也就是这个类的对象


verification(验证)

为了确保 Class 文件的字节流中包含的信息符合当前虚拟机的要求,,不会危害虚拟机自身的安全,这个阶段会 进行文件格式验证 **(是否以魔数 oxcafebabe开头),元数据验证,字节码验证,和符号引用验证

如果想要关闭大部分类验证措施,加快加载速度可以这样做

javac -Xverify:none HelloWorld.java

helloworld 是类名


Preparation(准备)

JVM 会在该阶段 对 静态变量!!!,分配内存并初始化(对应数据类型的默认初始值)。这些变量的 内存分配在方法区

注意这里是静态变量,不是静态的,加载阶段不会分配内存


Resolution (解析)

JVM 将常量池的 == 符号引用== 替换为 直接引用的过程

符号引用

将 Java 类文件中,以一组符号来描述类名,方法名等东西,这些符号与实际的内存地址没有关系

直接引用

将符号引用,直接替换为直接指向这些数据的指针或地址

还没分配内存的时候用符号引用类似于打个标记,这个时候分配内存在变成直接引用


initialization(初始化)

这个阶段才真正执行类中定义的 Java 程序代码,这个阶段也是执行 clinit() 方法的过程,这个方法会根据顺序,把静态变量的赋值动作,和静态代码块中的语句合并

clinit 方法在多线程的环境中会正确加锁,也就是线程是阻塞的,等一个线程 clinit 方法执行完,才放锁,让下一个线程用




获取 Class 对象

  • Class.forName(“全类名”):编译阶段创建
    全类名:包名 + 类名

多用于配置文件,最常用

//com.mangfu.test 包下的 Student 类
Class test = Class.forName("com.mangfu.test.Student" );

  • 类名.class:加载阶段创建,类加载器得到 Class 对象

多用于参数传递,比如通过反射得到对应构造器对象,这种方式 最安全,性能最高

Class clazz = Student.class

  • 对象.getClass():运行阶段创建

通过创建好的对象,获取 Class 对象

Student s = new Student();
Class clazz = s.getClass();

  • 基本数据类型.class

基本数据类型,创建 Class 对象的方法

Class clazz = int.class

  • 包装类.TYPE

基本数据类型对应的包装类,创建 Class 对象的放啊

Class clazz = Integer.class



反射获取构造方法:获取 Class 对象里面 Constructor 对象

Class类 中用于获取构造方法的方法

  • Constructor<?>[] getConstructors(): 返回所有公有构造方法对象的数组

  • Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组

  • Constructor getConstructor(Class<?>… parameteTypes):返回单个公有构造方法对象
    参数为 基本数据结构或者包装类的字节码,对象.class,这样可以获取有参构造

  • Constructor getDeclaredConstructor(Class<?>…parmeterTypes):返回单个构造方法对象
    参数为 基本数据结构或者包装类的字节码,对象.class,这样可以获取有参构造

Constructor:用构造方法对象创建对象的方法
Student类

  • T newinstance(Object…initargs):根据指定的构造方法创建对象
    参数(可变):是构造函数里面需要的参数

  • setAccessible(boolean flag):设置为 true, 表示取消访问检查

setAccessible:**使用反射可以访问 private 构造器 [称为爆破]


举个例子
主要看Main类

Student类

public class Student {
    private int age = 18;
    public String name = "张三";

    private Student() {}

    private Student(int age, String name) {
        this.age = age;
        this.name = name;
    }

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

Main 类

public class Main {
    public static void main(String[] args)throws Exception {
        Class clazz = Class.forName("com.mangfu.test.Student");

        //因为 构造方法是私有的 所以我们要用 getDeclaredConstructor
        //里面的参数是 形参的字节码
        Constructor cs = clazz.getDeclaredConstructor(int.class, String.class);

        //因为这个是私有对象,我们要通过爆破创建才能构造一个对象
        cs.setAccessible(true);

        //通过 newInstance 构造一个对象
        Student s = (Student) cs.newInstance(18, "张三");
        System.out.println(s);

    }
}


反射获取成员变量:获取Class 对象里面的 Field 对象

Class 类中用于获取成员变量的方法

  • Field[] getFields():返回所有公共成员变量对象的数组

  • Field[] getDeclaredFields():返回所有成员变量对象的数组

  • Field[] getField(String name):返回单个公有成员变量对象
    参数是 对象(不是Class对象,下面是Student 对象) 的属性名

  • Field getDeclaredField(String name):返回单个成员变量对象
    参数是 对象(不是Class对象,下面是Student 对象) 的属性名

Field 类中用于创建对象的方法

  • void set(Object obj, Object value):赋值
    参数1:field 对象,参数2:需要赋的值

  • Object get(Object obj):获取值
    参数:对象(不是Class 对象,下面是 Student 对象)的名字

  • setAccessible(boolean flag):设置为 true, 表示取消访问检查

举例
Student 类

public class Student {
    private int age = 18;
    private String name = "张三";

    private Student() {}

    private Student(int age, String name) {
        this.age = age;
        this.name = name;
    }

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

Main类

public class Main {
    public static void main(String[] args)throws Exception {

        //得到 Student 类的 Class 对象
        Class clazz = Class.forName("com.mangfu.test.Student");

        //获取 Class 对象里面的 Field 对象----属性 name
        Field field = clazz.getDeclaredField("name");

        //通过 反射利用构造函数构造对象
        Constructor cs = clazz.getDeclaredConstructor(int.class, String.class);
        cs.setAccessible(true);
        Student s = (Student) cs.newInstance(18, "张三");

        //因为这个属性是私有的 所以要用 setAccessible 爆破一下,才能修改
        field.setAccessible(true);

        //修改 属性 name 的 值,因为上面我们获取的 是属性 name 对象
        field.set(s, "李四");
        System.out.println(field.get(s));//输出李四

    }
}


反射获取成员方法:获取 Class 对象里的 Method 对象

Class类中用于获取成员方法的方法

  • Method[] getMethods():返回公有成员方法对象的数组,包括继承的

  • Method[] getDeclaredMethods:返回所有成员方法对象的数组,不包括继承的

  • Method getMethod(String name, Class<?>…parameterTypes):返回单个公有成员方法对象
    参数1:方法的名字,参数2:方法的形参(可变)

  • Method getDeclaredMethod(String name, Class<?>…parameterTypes):返回单个成员方法对象
    参数1:方法的名字,参数2:方法的形参(可变)

Method类中用于创建对象的方法

  • Object invoke(Object obj, Object…args):允许方法
    参数1: 对象(不是Class对象,下面是Student 对象),参数2:调用方法要传递的参数(没有就不写)。返回值:调用的方法的返回值的对象

  • setAccessible(boolean flag):设置为 true, 表示取消访问检查

举例
Student 类

public class Student {
    private int age = 18;
    private String name = "张三";

    public Student() {};

    private Student(int age, String name) {
        this.age = age;
        this.name = name;
    }

    private int hi() {
        System.out.println("调用hi函数");
        return 1;
    }

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

Main 方法

public class Main {
    public static void main(String[] args)throws Exception {

        //得到 Student 类的 Class 对象
        Class clazz = Class.forName("com.mangfu.test.Student");

        //得到 Student 中的 hi 方法的对象
        Method method = clazz.getDeclaredMethod("hi");

        //这里 通过反射 构造 Student 类对象
        Constructor constructor = clazz.getConstructor();
        Student s = (Student) constructor.newInstance();

        //通过反射调用 Student 类中的 hi 方法,因为我们上面的得到的 Method 对象是 hi 方法
        //而且这个方法是私有的所以要爆破一手
        method.setAccessible(true);
        method.invoke(s);

    }
}



其他常用 API

Class
在这里插入图片描述


Constructor

Parmeter[] getrParmameters():获取构造方法的形参

int getmodifiers():获取成员变量的数据类型


Field

int getmodifiers():获取成员变量的数据类型
Class<?> getType:获取成员变量的数据类型
String getName:获取成员变量的名字


Method

int getmodifiers():获取成员变量的数据类型
Class[] getExceptionTypes:获取方法抛出的异常
String getName:获取成员变量的名字
Class[] getParameter():获取方法的形参,以 Class[] 形式返回
Class getReturnType:以Class 形式获取返回类型


getmodifiers() 方法返回值

默认修饰符号:0,public:1,private:2,protected:3,static:8,final:16




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

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

相关文章

融合创新,共筑未来 | 人大金仓为轨道交通发展注入新质力量

METROTRANS 2024 6月13日~15日&#xff0c;以“多元融合 高质量可持续发展”为主题的2024北京-南京国际城市轨道交通展览会暨高峰论坛在南京国际博览中心隆重举行。人大金仓受邀亮相本次大会&#xff0c;展示了其在轨道交通的创新应用和解决方案。 ‍点击视频 直击现场‍ 规模最…

机器学习课程复习——奇异值分解

1. 三种奇异值分解 奇异值分解&#xff08;Singular Value Decomposition, SVD&#xff09;包含了&#xff1a; 完全奇异值分解&#xff08;Complete Singular Value Decomposition, CSVD&#xff09;紧奇异值分解&#xff08;Tight Singular Value Decomposition, TSVD&…

年终奖发放没几天,提离职领导指责我不厚道,我该怎么办?

“年终奖都发了&#xff0c;你还跳槽&#xff1f;太不厚道了吧&#xff01;” “拿完年终奖就走人&#xff0c;这不是典型的‘骑驴找马’吗&#xff1f;” 每到岁末年初&#xff0c;关于“拿到年终奖后是否应该立即辞职”的话题总会引发热议。支持者认为&#xff0c;这是个人…

GLSB是什么?带你深入了解GLSB核心功能

伴随互联网的快速发展&#xff0c;大型企业等组织单位通过建设多数据中心&#xff0c;以提升用户体验。然而想要在多个数据中心实现流量的智能管理&#xff0c;提高网站的可靠性和可用性&#xff0c;则需要全局服务器负载均衡技术——GLSB的助力。GLSB是什么&#xff1f;它又有…

笔记本系统盘移植与windowsLinux双系统安装

目录 一、 前言二、 Windows系统移植二、 安装Linux三、 Windows分区配置 一、 前言 笔记本内存不够了&#xff0c;之前给笔记本添加了一个机械硬盘&#xff0c;也几乎爆满了&#xff0c;于是购置了1T的固态硬盘&#xff0c;打算用这个固态硬盘安装双系统&#xff0c;剩余空间…

【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【11】ElasticSearch

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【11】ElasticSearch 简介基本概念ElasticSearch概念-倒排索引安装基本命令ik 分词器SpringBoot整合测试存储数据&#xff1a;测试复杂检索同步与异步调用 参考 简介 Elasticsearch 是一…

【UE数字孪生学习笔记】 Apifox一体化接口测试平台

声明&#xff1a;部分内容来自于b站&#xff0c;知乎&#xff0c;慕课&#xff0c;公开课等的课件&#xff0c;仅供学习使用。如有问题&#xff0c;请联系删除。 部分内容来自UE官方文档&#xff0c;博客等 Apifox接口测试 Apifox 是集 API 文档、API 调试、API Mock、API 自动…

DDMA信号处理以及数据处理的流程---距离速度测量

Hello,大家好,我是Xiaojie,好久不见,欢迎大家能够和Xiaojie一起学习毫米波雷达知识,Xiaojie准备连载一个系列的文章—DDMA信号处理以及数据处理的流程,本系列文章将从目标生成、信号仿真、测距、测速、cfar检测、测角、目标聚类、目标跟踪这几个模块逐步介绍,这个系列的…

腾讯《地下城与勇士:起源》手游在部分安卓平台停止更新

原标题&#xff1a;因合约到期 《DNF手游》停止安卓平台更新 易采游戏网6月19日消息&#xff1a;《地下城与勇士&#xff1a;起源》(简称DNF手游)官方今天公告&#xff0c;因合作协议到期&#xff0c;自6月20日起&#xff0c;该游戏将不再在某些安卓应用商店提供。腾讯公司已经…

OpenAI 发布多模态 GPT-4 模型,会开创哪些新的研究方向?

作者&#xff1a;JioNLP 链接&#xff1a;https://www.zhihu.com/question/589640227/answer/2936760622 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 短期看&#xff0c;GPT4 就是个终结者 。开创不了什么新的方…

Redis学习|Jedis、SpringBoot整合Redis

Jedis 我们要使用Java 来操作 Redis,知其然并知其所以然&#xff0c;授人以渔!学习不能急躁&#xff0c;慢慢来会很快!什么是Jedis 是 Redis 官方推荐的java连接开发工具!使用java 操作Redis 中间件!如果你要使用 java操作redis&#xff0c;那么一定要对Jedis 十分的熟悉! 1、…

C++初学者指南第一步---7.控制流(基础)

C初学者指南第一步—7.控制流&#xff08;基础&#xff09; 文章目录 C初学者指南第一步---7.控制流&#xff08;基础&#xff09;1.术语:表达式/语句Expressions表达式Statements语句 2.条件分支3.Switching(切换):基于值的分支4.三元条件运算符5.循环迭代基于范围的循环   C…

STM32人工智能检测-筛选机器人

前言 本文描述了一种使用STM32进行机器人筛选的办法。筛选对象是我的粉s&#xff0c;删选办法是瞪眼法。 问题现象 每次当我的STM32 向外界发出一篇新的的报文&#xff0c;总能在1H之内得到focus&#xff0c;格式如下 [title][body][tail]于是我对各个focus 我报文的对象进…

Midjourney和Stable Diffusion哪个更适合商业应用?

midjourney的绘画&#xff0c;在撰写有效的prompt需要精确地定义你想要展现的画面&#xff0c;详细描述越准确&#xff0c;生成出的图片结果也会越吻合你的预期。为了提升你midjourney的写作prompt的技巧&#xff0c;可以通过模仿他人的成功案例&#xff0c;亲自尝试编写&#…

UWA发布 | Unity手游性能年度蓝皮书

UWA本次发布的《2023-2024年度Unity手游性能蓝皮书》将汇总游戏行业使用Unity引擎进行手游开发过程中及游戏上线后的性能表现&#xff0c;从测试机型分布、引擎各模块开销、内存占用等方面剖析定位Unity手游性能瓶颈和趋势&#xff0c;反映了Unity手游行业的现状&#xff0c;帮…

202483读书笔记|《牵牛花浮世无篱笆:千代尼俳句250》——被红叶染红的只有一侧山坡之山 啊,单恋

202483读书笔记|《牵牛花浮世无篱笆&#xff1a;千代尼俳句250》——被红叶染红的只有一侧山坡之山 啊&#xff0c;单恋 春之句夏之句秋之句冬之句 历史读过的俳句列表: 202318读书笔记|《芭蕉芜村一茶&#xff1a;俳句三圣新译300》——樱花——让一整个春夜亮起来&#xff0…

MPLS静态配置实验(初学版)

实验拓扑 配置接口地址 配置OSPF协议 测试网络连通性 配置静态MPLS AR1&#xff1a; [R1]mpls lsr-id 1.1.1.1 [R1]mpls [R1-GigabitEthernet0/0/0]mpls [R1]static-lsp ingress wps destination 4.4.4.4 32 nexthop 10.1.12.2 outgoing-interface g0/0/0 out-label 100AR2 [R2…

【第20章】Vue实战篇之Vue Router(路由)

文章目录 前言一、使用Vue-Router1.安装2. 创建路由器实例3. 注册路由器插件4. 根组件 二、访问路由器1.理论2.使用3. 展示 三、嵌套路由(子路由)1. 准备文件2. 配置路由3. 菜单配置4. 展示 总结 前言 Vue Router 是 Vue.js 的官方路由。它与 Vue.js 核心深度集成&#xff0c;…

VMware RedHat虚拟机磁盘扩容(添加磁盘和扩展磁盘)

前言 自己的电脑上配一个虚拟机还是很有必要的&#xff0c;用起来比双系统方便一点&#xff0c;之前搞了100g的ubuntu没用到&#xff0c;后面重装redhat觉得随便搞个20g就够用了&#xff0c;后面用到之后就遇到磁盘不够用的情况&#xff0c;只能说情况允许的话&#xff0c;磁盘…

SambaLingo——教会大模型新语言

在当今数字化时代&#xff0c;语言不仅是沟通的桥梁&#xff0c;也是信息和知识传递的核心。尽管大模型&#xff08;LLMs&#xff09;在处理英语等主流语言方面取得了显著进展&#xff0c;但它们在理解和生成其他语言内容方面的能力却参差不齐。这种不平衡限制了技术在全球范围…