反射机制(Reflection)

news2024/11/24 6:54:46

在这里插入图片描述


1. 反射

Java的反射机制(reflection)是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射(reflection)机制
#反射存在的意义

  1. 在日常的第三方开放中,我们经常会遇到某个类的某个成员变量、方法是私有的属性或是只针对系统应用开放,当我们想要获得其中的私有成员或是方法的时候就可以通过Java的反射机制来反射获取
  2. 用于各种通过框架的开发(了解)

1.1 反射相关的类

类名作用
Class类表示类的实体,在运行的Java应用程序中表示类和接口
Field类)表示类的成员变量/类的属性
Method类)表示类的方法
Constructor类)表示类的构造方法

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

在这里插入图片描述

1.2 Class对象的获取

在反射之前,我们需要做的第一步就是先拿到当前需要反射的类的Class对象,然后通过Class对象的核心方法,达到反射的目的,即:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,从而进行对类的操作。

获取Class对象主要有以下三种方法:

  1. 使用每个类都隐含的静态成员变量class–(.class())
  2. 使用类对象的getClass()方法
  3. 使用Class.forName("类的全路径名"),类的全路径名,如果有包需要加包的路径
public class Test {  
    public static void main(String[] args) {   
        //1.通过getClass获取Class对象     
        Person person1 = new Person();  
        Class c1 = person1.getClass();  
		System.out.println(c1);
        /*  
        2.直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高  
		这说明任何一个类都有一个隐含的静态成员变量 class       
		*/       
		Class c2 = Person.class; 
		System.out.println(c2); 
        /*  
        3、通过 Class 对象的 forName() 静态方法来获取,用的最多,  
        但可能抛出 ClassNotFoundException 异常 ,搜查异常必须手动处理 
        */        
        Class c3 = null;  
        try {  
            c3 = Class.forName("Person");  
            System.out.println(c3);
        } catch (ClassNotFoundException e) {  
            throw new RuntimeException(e);  
        }  
        //一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的  
        //c1,c2,c3进行 equals 比较,发现都是true  
        System.out.println(c1.equals(c2));  
        System.out.println(c1.equals(c3));  
        System.out.println(c2.equals(c3));  
    }  
}

运行结果如下:
在这里插入图片描述

我们通过三个Class对象的比较得出一个类在JVM中只会有一个Class实例,即c1、c2、c3通过equals()比较,结果都是true

1.3 Class类中的相关方法

  • 获得类的相关方法
    在这里插入图片描述

  • 获得类中属性相关的方法
    在这里插入图片描述

  • 获得类中注解相关的方法
    在这里插入图片描述

  • 获得类中构造器相关的方法
    在这里插入图片描述

反射的使用

import java.lang.reflect.Constructor;  
import java.lang.reflect.Field;  
import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;  
  
public class Test {  
    public static void reflectNewInstance() {  
        try {  
            Class<?> classPerson = Class.forName("Person");  
            Object objectPerson = classPerson.newInstance();//类型擦除  
            Person person = (Person)objectPerson;  
            System.out.println("获得Person对象:" + person);  
        } 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() {  
        try {  
            Class<?> classPerson = Class.forName("Person");  
            //注意传入对应的参数  
            Constructor<?> declaredConstructorPerson = classPerson.getDeclaredConstructor(String.class,int.class);  
            //Constructor<?> declaredConstructorPerson = classPerson.getConstructor();//(1)  
  
            //对于存在私有构造方法的使用需要给予访问许可  
            declaredConstructorPerson.setAccessible(true);  
            Object objectPerson = declaredConstructorPerson.newInstance("李四",21);  
            //Object objectPerson = declaredConstructorPerson.newInstance();//(1)  
            Person Person = (Person)objectPerson;  
            System.out.println("获得私有构造哈数且修改姓名和年龄:"+ Person);  
        } catch (ClassNotFoundException e) {  
            throw new RuntimeException(e);  
        } catch (InvocationTargetException 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);  
        }  
    }  
    // 反射私有属性  
    public static void reflectPrivateField() {  
        try {  
            Class<?> classPerson = Class.forName("Person");  
            Field field = classPerson.getDeclaredField("name");  
            //对于私有属性获取后的使用需要给予访问许可  
            field.setAccessible(true);  
            Object objectPerson = classPerson.newInstance();  
            Person person = (Person) objectPerson;  
            //可以修改该私有属性的值,需要先实例一个对象  
            field.set(person,"王五");  
            String name = (String)field.get(person);  
            System.out.println("反射私有属性修改了name:"+ name);  
        } catch (NoSuchFieldException e) {  
            throw new RuntimeException(e);  
        } catch (ClassNotFoundException e) {  
            throw new RuntimeException(e);  
        } catch (InstantiationException e) {  
            throw new RuntimeException(e);  
        } catch (IllegalAccessException e) {  
            throw new RuntimeException(e);  
        }  
    }  
    // 反射私有方法  
    public static void reflectPrivateMethod() {  
        try {  
            Class<?> classPerson = Class.forName("Person");  
            Method methodPerson = classPerson.getDeclaredMethod("function",String.class);  
            System.out.println("私有方法的方法名为:"+methodPerson.getName());  
            //对于私有方法获取后的使用需要给予访问许可  
            methodPerson.setAccessible(true);  
            Object objectPerson = classPerson.newInstance();  
            Person person = (Person) objectPerson;  
            methodPerson.invoke(person,"通过反射获取私有方法function函数并使用该函数");  
        } catch (ClassNotFoundException e) {  
            throw new RuntimeException(e);  
        } catch (InvocationTargetException 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);  
        }  
    }  
    public static void main(String[] args) {  
        System.out.println("======= reflectNewInstance(),通过反射实例类对象 =======");  
        reflectNewInstance();  
        System.out.println("======= reflectPrivateConstructor(),反射私有构造方法 =======");  
        reflectPrivateConstructor();  
        System.out.println("======= reflectPrivateField(),反射私有属性 =======");  
        reflectPrivateField();  
        System.out.println("======= reflectPrivateMethod(),反射私有方法 =======");  
        reflectPrivateMethod();  
    }  
}

运行结果如下:
在这里插入图片描述

在反射的使用过程中,需要特别注意的是当使用私有性质的方法/属性时应当先设置许可。

1.4 反射的优缺点

优点:

  1. 对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法

  2. 增加程序的灵活性和扩展性,降低耦合性,提高自适应能力

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

缺点:

  1. 使用反射会有效率问题。会导致程序效率降低

  2. 反射技术绕过了源代码的技术,因而会带来维护问题。反射代码比相应的直接代码更复杂 。

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

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

相关文章

创建一个c#程序,实现字符串类型转整数类型

首先&#xff0c;创建一个c#程序 在代码编辑器中编写代码&#xff0c;点击Run按钮或者按下F5键来运行程序。 下面&#xff0c;编写将字符串类型转换为整数类型的代码。 sing System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Task…

安装samples/1_Utilities/deviceQuery等文件

本文章摘抄来自https://zhuanlan.zhihu.com/p/666647168 从cuda11.6开始cuda toolkit就不自带cuda-samples了&#xff0c;而deviceQuery又是cuda-sample的一个子库&#xff0c;所以需要自己手动装一下。 我的系统是ubuntu20.04&#xff0c;已经安装了CUDA Toolkit 12.2。 第…

【深度学习】使用FasterRCNN模型训练自己的数据集(记录全流程

此处用的FasterRCNN模型使用的是B导的源码&#xff0c;读者可以去B站搜B导的视频进行了解和学习&#xff0c;视频中B导非常细心讲解了如何训练自己的数据集以及预测。 文章目录 前言一、准备数据集二、环境配置2.1 基础环境2.2 其他依赖包安装2.3 预训练权重下载 二、训练数据集…

程序员成长秘籍:是迈向管理巅峰,还是深耕技术架构?

专业在线打字练习平台-巧手打字通&#xff0c;只输出有价值的知识。 一 管理和架构 做技术的同学一般有两条职业发展路径&#xff0c;横向的管理路线和纵向的技术路线。管理路线对应的是管理岗&#xff0c;讲究的是排兵布阵&#xff0c;通过各种资源的优化配置发挥价值。技术路…

(Linux驱动学习 - 10).MISC驱动实验

一.MISC介绍 1.MISC定义 misc 的意思是混合、杂项的&#xff0c;因此 MISC 驱动也叫做杂项驱动&#xff0c;也就是当我们板子上的某 些外设无法进行分类的时候就可以使用 MISC 驱动。 MISC 驱动其实就是最简单的字符设备驱 动&#xff0c;通常嵌套在 platform 总线驱动中&…

智能贴身监测,健康生活建议,圆道妙医智能手表体验

如今热衷于运动和健康生活的爱好者越来越多&#xff0c;相关的赛事等活动也是逐年增多&#xff0c;很多朋友为了能够直观的了解自己的健康状况&#xff0c;都会配备一款智能手表&#xff0c;这样戴在身上就可以随时了解自己的心率、血氧等数据。最近我尝试了一款圆道妙医推出的…

MobaXterm连接Cloudflare Tunnel内网穿透的SSH

背景 如官方文档所示&#xff0c;Cloudflare Tunnel要求我们对SSH客户端进行配置&#xff0c;使本地的cloudflared软件代理SSH才能连接。 存在问题 由于MobaXterm的Session实质为嵌入式PuTTY&#xff0c;不使用OpenSSH样式的配置文件&#xff08;即~/.ssh/config&#xff09…

SpringBoot框架下购物推荐网站的设计模式与实现

3系统分析 3.1可行性分析 通过对本东大每日推购物推荐网站实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本东大每日推购物推荐网站采用JAVA作为开发语言&…

对层级聚类树进行模块分割,定位基因在哪个模块中

拷贝数据到 ImageGP (http://www.ehbio.com/Cloud_Platform/front/#/analysis?pageb%27Ng%3D%3D%27)&#xff0c;并设置参数. ID untrt_N61311 untrt_N052611 untrt_N080611 untrt_N061011 trt_N61311 trt_N052611 trt_N080611 trt_N061011 ENSG000…

【ROS2实操二】服务通信

简介 服务通信也是ROS中一种极其常用的通信模式&#xff0c;服务通信是基于请求响应模式的&#xff0c;是一种应答机制。也即&#xff1a;一个节点A向另一个节点B发送请求&#xff0c;B接收处理请求并产生响应结果返回给A。比如如下场景&#xff1a;机器人巡逻过程中&#xff0…

cuda入门学习

最近接触cuda 编程&#xff0c;记录一下。 1 工作实现一个【0-100&#xff09;的加法 如果用python sum 0 for i in range(200):sumi print(sum)2 cuda 的一些简单的概念 一维情况下大概是这样的 (1个grid * 2个blocks * 4个thread) 3 代码直接上代码 我把100分为20个b…

Jenkins---01

什么是敏捷开发 敏捷开发以用户的需求进化为核心&#xff0c;采用迭代、循序渐进的方法进行软件开发。在敏捷开 发中&#xff0c;软件项目在构建初期被切分成多个子项目&#xff0c;各个子项目的成果都经过测试&#xff0c;具备可视、 可集成和可运行使用的特征。换言之&…

2024年编程资料【9月份部分】

资料列表 「CSDN会员免费电子书1000本」 https://pan.quark.cn/s/5019390a751a 【黑马程序员】年度钻石会员-人工智能AI进阶 https://pan.quark.cn/s/1d14a2a179c2 JavaScript从入门到高级教程 - 带源码课件 https://pan.quark.cn/s/c16ed07eac93 【马哥教育】云原生微服务治理…

测试常用插件: ModHeader - Modify HTTP headers插件进行IP模拟/IP欺骗

由于公司是做海外项目的&#xff0c;所以付款时有要求进行模拟不同IP登录进去时会优先显示该地区的支付方式。 1.安装插件 这里以Microsoft Edge为例&#xff0c;打开扩展 搜索&#xff1a;ModHeader - Modify HTTP headers&#xff0c;进行获取安装即可 安装完成后&#xff…

CVESearch部署、使用与原理分析

文章目录 前言1、概述2、安装与使用2.1、源码安装2.1.1、部署系统依赖组件2.1.1.1、下载安装基础组件2.1.1.2、下载安装MongoDB Community Edition 7.0 2.1.2、使用源码安装系统2.1.2.1、安装CVESearch2.1.2.2、填充MongoDB数据库2.1.2.3、填充Redis数据库 2.2、使用方法 3、测…

LeetCode | 704.二分查找

标准的二分查找&#xff0c;直接上模板&#xff01; class Solution(object):def search(self, nums, target):""":type nums: List[int]:type target: int:rtype: int"""l 0r len(nums) - 1while l < r:mid (l r 1) / 2if nums[mid] …

Telnet命令详解:安装、用法及应用场景解析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

笔试算法总结

文章目录 题目1题目2题目3题目4 题目1 使用 StringBuilder 模拟栈的行为&#xff0c;通过判断相邻2个字符是否相同&#xff0c;如果相同就进行删除 public class Main {public static String fun(String s) {if (s null || s.length() < 1) return s;StringBuilder builde…

EventLoop模块 --- 事件循环模块

目录 1 设计思想 eventfd 创建eventfd 2 实现 3 联合调试 4 整合定时器模块 5 联合超时模块调试 1 设计思想 EventLoop 模块是和线程一一绑定的&#xff0c;每一个EventLoop模块内部都管理了一个Poller对象进行事件监控&#xff0c;同时管理着多个Connection对象&…

python 使用faker库 生成数据

Welcome to Faker’s documentation! — Faker 30.3.0 documentationVersion1: Example from docs:from faker import Faker from faker.providers import internet for i in range(2): #批量生成数据fake Faker()name fake.name()address fake.address()text f…