反射的原理和操作

news2024/11/19 4:19:50

反射是框架设计的灵魂

(使用的前提条件:必须先得到代表的字节码的Class,Class类用于表示.class文件(字节码))

在Java中,反射是指在运行时动态地获取、检查和操作类、对象、方法和属性的能力。Java的反射机制提供了一组API,使程序可以在运行时获取类的信息,并通过这些信息来创建对象、调用方法和访问属性,而无需在编译时提前知道类的具体细节。

通过反射,可以实现以下操作:

  1. 动态创建对象:可以使用反射来实例化一个类的对象,即使在编译时并不知道类的名称。例如,可以动态地根据类名创建对象实例,并调用其方法。

  2. 获取类的信息:可以使用反射来获取类的名称、修饰符、父类、接口等信息。还可以获取类的构造函数、方法和字段的详细信息,包括名称、参数类型、修饰符等。

  3. 调用方法:可以使用反射来调用类的方法,包括公共方法、私有方法和静态方法。通过Method类的实例,可以动态地调用方法并传递参数。

  4. 访问和修改字段:可以使用反射来获取和设置类的字段的值。通过Field类的实例,可以读取和修改对象的字段,包括公共字段和私有字段。

  5. 动态代理:反射还可以用于实现动态代理,即在运行时动态生成代理对象并拦截方法调用。这对于实现AOP(面向切面编程)和其他类似的功能非常有用。

底层原理

通常,java在编译之后,会将Java代码生成为class源文件,JVM启动时,将会载入所有的源文件,并将类型信息存放到方法区中;将所有对象实例存放在Java堆中,同时也会保存指向类型信息的指针。

与直接使用类相反,我们需要先获取到对象在方法区的类型信息,获取到类型信息后,我们就知道这个类的构造器、属性、方法、注解、子类、父类等等信息了,这个时候,我们就可以通过这些类型信息来回调处理对象,来完成自己想要的操作了。

没错,这就是反射的原理了。反射在运行时,通过读取方法区中的字节码,来动态的找到其反射的类以及类的方法和属性等(实际上就是在运行时,根据全类型名在方法区找对应的类),用这些类型信息完成对该类实例的操作,其实就是直接使用类的一个逆向使用。

如果我们动态获取到这些信息,我们需要依靠 Class 对象。Class 类对象将一个类的方法、变量等信息告诉运行的程序。

Java 提供了四种方式获取 Class 对象:

1. 知道具体类的情况下可以使用:

Class alunbarClass = TargetObject.class;

但是我们一般是不知道具体类的,基本都是通过遍历包下面的类来获取 Class 对象,通过此方式获取 Class 对象不会进行初始化

2. 通过 Class.forName()传入类的全路径获取:

Class alunbarClass1 = Class.forName("cn.javaguide.TargetObject");

3. 通过对象实例instance.getClass()获取:

TargetObject o = new TargetObject();
Class alunbarClass2 = o.getClass();

4. 通过类加载器xxxClassLoader.loadClass()传入类路径获取:

ClassLoader.getSystemClassLoader().loadClass("cn.javaguide.TargetObject");

通过类加载器获取 Class 对象不会进行初始化,意味着不进行包括初始化等一系列步骤,静态代码块和静态对象不会得到执行


   创建一个我们要使用反射操作的类 TargetObject

package cn.javaguide;

public class TargetObject {
    private String value;

    public TargetObject() {
        value = "JavaGuide";
    }

    public void publicMethod(String s) {
        System.out.println("I love " + s);
    }

    private void privateMethod() {
        System.out.println("value is " + value);
    }
}
  1. 使用反射操作这个类的方法以及参数
package cn.javaguide;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchFieldException {
        /**
         * 获取 TargetObject 类的 Class 对象并且创建 TargetObject 类实例
         */
        Class<?> targetClass = Class.forName("cn.javaguide.TargetObject");
        TargetObject targetObject = (TargetObject) targetClass.newInstance();
        /**
         * 获取 TargetObject 类中定义的所有方法
         */
        Method[] methods = targetClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }

        /**
         * 获取指定方法并调用
         */
        Method publicMethod = targetClass.getDeclaredMethod("publicMethod",
                String.class);

        publicMethod.invoke(targetObject, "JavaGuide");

        /**
         * 获取指定参数并对参数进行修改
         */
        Field field = targetClass.getDeclaredField("value");
        //为了对类中的参数进行修改我们取消安全检查
        field.setAccessible(true);
        field.set(targetObject, "JavaGuide");

        /**
         * 调用 private 方法
         */
        Method privateMethod = targetClass.getDeclaredMethod("privateMethod");
        //为了调用private方法我们取消安全检查
        privateMethod.setAccessible(true);
        privateMethod.invoke(targetObject);
    }
}

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

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

相关文章

第2章 Rust初体验3/8:使用Result进行错误处理:编译时错误检查增强代码安全性:猜骰子冷热游戏

讲动人的故事,写懂人的代码 2.3.9 类型的关联函数:简化对象创建和初始化 席双嘉:“那个String::new(),毫无疑问,它确实像C++中的静态成员函数。” 贾克强:“哈哈!是的,两个冒号确实让人联想到一些东西,对吧?” “这其实是Rust中的关联函数(associated function,详…

第四集《唯识与净土》

请大家打开讲义第十面。 我们讲到念佛的功德有两个&#xff1a;第一个是“现世的安乐”&#xff0c;第二个是“来世究竟的解脱”。 这个净土法门的特色&#xff0c;是一种本尊相应法。 也就是说&#xff0c;我们在整个修行破恶生善的过程当中&#xff0c;主要是要仰仗本尊的…

设计师必看|精选免费icon生成网站推荐

在平面设计过程中&#xff0c;如何收集icon素材&#xff1f;(opens in a new tab or window)&#xff1f; 在这里我们为您准备了三个免费、易用的icon生成网站&#xff0c;需要icon材料的同学&#xff0c;记得点赞收藏。 01∣即时设计 作为国内领先的在线设计平台&#xff0…

创建第一个Springboot项目(环境准备、环境存在的问题、启动时存在的问题、启动的方式)

一、环境准备 专业版创建springboot&#xff0c;直接有一个选项可以选择 社区版&#xff0c;需要下载一个spring的插件 不要直接点 install 因为这个插件是付费的&#xff0c;直接点安装只有30天使用期限 在里面找免费版本的下载 然后安装 安装完成后&#xff0c;这个插件名会变…

作为程序员,科班计算机比起非科班有很大优势吗?

在当今这个快速变化的时代&#xff0c;个人的能力与优势成为了职场竞争中的关键因素。在众多的职业选择中&#xff0c;程序员因其独特的技能和市场需求而备受青睐。 然而&#xff0c;并非所有人在18岁就决定要进入计算机行业&#xff0c;许多人都是在大学毕业之后由于种种原因…

一步步教你用Python Selenium抓取动态网页任意行数据

引言 在现代网络中&#xff0c;动态网页越来越普遍&#xff0c;这使得数据抓取变得更具挑战性。传统的静态网页抓取方法在处理动态内容时往往力不从心。本文将详细介绍如何使用Python Selenium抓取动态网页中的任意行数据&#xff0c;并结合代理IP技术以提高抓取的成功率和效率…

PostgreSQL源码分析——缓冲区管理器

这里我们分析一下PG数据库缓冲区的代码。缓冲区是十分重要的&#xff0c;对数据库的性能和稳定性有着直接的影响。缓冲区是数据库SQL计算层与外部存储&#xff08;磁盘&#xff09;交互的关键。数据页的落盘与读取&#xff0c;都要经过缓冲区。 README src/backend/storage/…

本地部署AI模型-phi3

What&#xff1a; Phi-3-Mini被认为是Microsoft计划发布的三款小型机型中的首款。据报道&#xff0c;在语言、推理、编码和数学等领域&#xff0c;它在各种基准测试中的表现优于相同大小和下一个尺寸的模型。 从本质上讲&#xff0c;语言模型是 ChatGPT、Claude、Gemini 等 AI…

WPF/C#:显示分组数据的两种方式

前言 本文介绍自己在遇到WPF对数据进行分组显示的需求时&#xff0c;可以选择的两种方案。一种方案基于ICollectionView&#xff0c;另一种方案基于IGrouping。 基于ICollectionView实现 相关cs代码&#xff1a; [ObservableProperty] private ObservableCollection<Peo…

变声方法大公开,变女声很自然的3款变声器推荐,值得收藏

将男声变成女声并且要很自然的变声器有吗&#xff1f;很多喜欢玩游戏的小伙伴们在进行游戏连麦时&#xff0c;可能为了增加趣味&#xff0c;想要试试变成女声来交流&#xff0c;或者喜欢视频剪辑创作的小伙伴们在进行视频配音时&#xff0c;不想用自己的声音出镜&#xff0c;需…

WGCLOUD的web ssh提示websocket服务连接已断开

这个问题一般是server主机没有开放端口9998&#xff0c;因为9998是web ssh的端口&#xff0c;需要开放 我们只要在防火墙&#xff0c;或者安全软件&#xff0c;把这个端口开放了就可以了

STM32HAL库--NVIC和EXTI

1. 外部中断实验 1.1 NVIC和EXTI简介 1.1.1 NVIC简介 NVIC 即嵌套向量中断控制器&#xff0c;全称 Nested vectored interrupt controller。是ARM Cortex-M处理器中用于管理中断的重要组件。负责处理中断请求&#xff0c;分配优先级&#xff0c;并协调中断的触发和响应。 它是…

Scikit-Learn支持向量机回归

Scikit-Learn支持向量机回归 1、支持向量机回归1.1、最大间隔与SVM的分类1.2、软间隔最大化1.3、支持向量机回归1.4、支持向量机回归的优缺点2、Scikit-Learn支持向量机回归2.1、Scikit-Learn支持向量机回归API2.2、支持向量机回归初体验2.3、支持向量机回归实践(加州房价预测…

氮化铝与氧化铍用于大功率电阻器产品

在过去的几十年里&#xff0c;氧化铍&#xff08;BeO&#xff09;一直是用于高功率应用的射频电阻器和端接的主要基板材料。虽然BeO非常适合电子行业的大功率应用&#xff0c;但其粉尘颗粒是有毒的;如果吸入BeO颗粒&#xff0c;它们可能会导致铍中毒&#xff0c;即肺部炎症。由…

202406最新manjaro安装sogou输入法解决方案(采用aur本地package+sogo deb包解决方案)

本地执行安装方法 1.拉取源码 git clone https://gitee.com/liushuai05/fcitx-sogoupinyin.git cd fcitx-sogoupinyin 2.获取sogo下载地址并替换到源码中 - 下载地址&#xff1a;https://pinyin.sogou.com/linux/ - 点击立即下载->x86_64->下载&#xff0c;然后右键复制…

vue+echarts实现tooltip轮播

效果图如下&#xff1a; 实现步骤如下&#xff1a; 定义一个定时器 timer:null, len: 0,页面一加载就清空定时器&#xff0c;此操作是为了防止重复加载时会设置多个定时器在setOption后设置定时器 this.myChart.clear() this.myChart.setOption(option); this.autoShowTool…

AbMole带你探索颅内压力与肌肉生长的联系:一项突破性研究

在生物医学领域&#xff0c;颅内压力&#xff08;ICP&#xff09;的调控机制一直是研究的热点。最近&#xff0c;一项发表在《PLOS ONE》上的研究为我们揭示了颅内压力与后颅窝肌肉生长之间的潜在联系&#xff0c;为我们理解某些慢性头痛的成因提供了新的视角。 颅内压力的异常…

Ubuntu-24.04-live-server-amd64启用ssh

系列文章目录 Ubuntu-24.04-live-server-amd64安装界面中文版 Ubuntu安装qemu-guest-agent Ubuntu乌班图安装VIM文本编辑器工具 文章目录 系列文章目录前言一、输入安装命令二、使用私钥登录&#xff08;可选&#xff09;1.创建私钥2.生成三个文件说明3.将公钥复制到服务器 三…

抖音新规发布后,做抖音外卖代理需要注意什么?

近日&#xff0c;抖音发布了关于新增《【到家外卖】内容服务商开放准入公告》的意见征集通知&#xff08;以下简称“通知”&#xff09;&#xff0c;吹响了抖音外卖全面开放的号角&#xff0c;抖音外卖代理怎么做等问题也随即成为了众多创业者交流群中的热议话题。 根据通知要求…

【MySQL】(基础篇十二) —— 子查询

分组数据 本文介绍什么是子查询以及如何使用它们。 SQL允许我们创建子查询&#xff08;subquery&#xff09;&#xff0c;即嵌套在其他查询中的查询。这样可以实现更复杂的查询&#xff0c;理解这个概念的最好方法是考察几个例子。 利用子查询进行过滤 需求&#xff1a;查询…