Java反射机制

我是南城余!阿里云开发者平台专家博士证书获得者!

欢迎关注我的博客!一同成长!

一名从事运维开发的worker,记录分享学习。

专注于AI,运维开发,windows Linux 系统领域的分享!

本章节对应知识库

反射机制 · 语雀


反射

Java给我们提供的一套API,使用这套API可以在运行时动态获取指定对象所属的类,创建运行时类的对象,调用指定的结构(属性、方法)等。

Reflection(反射)是被视为动态语言的关键,反射机制允许程序在运行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

面向对象,调用指定结构(属性、方法)等功能,使用反射与不使用的区别

不使用反射,我们需要考虑封装性。比如出了Person类之后,就不能调用Person类中私有的结构

使用反射,我们可以调用运行时类中任意的构造器、属性、方法。包括了私有的属性、方法、构造器。

反射与创建对象调用方法的方式使用场景

》从作为开发者角度,我们开发中主要是完成业务代码,对于相关的对象、方法的调用都是确定的。所以在开发中,我们使用非反射的方式多一些。

》因为反射体现了动态性(可以在运行时动态的获取对象所属的类,动态的调用相关的方法),所以我们在涉及框架时,会使用大量的反射。意味着,如果需要学习框架源码时,那么就需要学习反射。

框架 = 注解+反射+设计模式

封装性:体现的是是否建议我们调用内部api的问题。比如,private声明的结构,意味着不建议调用

反射: 体现的是我们能否调用的问题。因为类的完整结构都加载了内存中,所以我们就有能力进行调用

反射的优缺点

优点:

》提高了Java程序的灵活性和扩展性,降低了耦合性,提高了自适应能力

》允许程序创建个控制任何类的对象,无需提前硬编码目标类

缺点:

》反射的性能较低

反射机制主要应用在对灵活性和扩展性要求很高的系统框架上

》反射会模糊程序内部逻辑,可读性较差

反射,平时开发中,我们使用的并不多。主要是在框架的底层使用

class - 反射的源头

针对于编写好的。java源文件进行编译(使用javac.exe)会生成一个或多个.class字节码文件。接着,我们使用java.exe命令对指定的.class文件进行解释运行。在这个解释运行的过程中,我们需要将.class字节码文件加载(使用类的加载器)到内存中(存在方法区)。加载到内存中的.class文件对应的结构即为Class的一个实例。

比如:加载到内存中的Person类或String类,都作为Class的一个一个的实例

Class clazz1 = Person.class;

Class clazz1 =String.class;


class可以看作是反射的源头

获取Class实例的几种方式

方式1:要求编译期间已知类型

前提:若已知具体的类,通过类的class属性获取,该方法最为安全可靠,程序性能最高

实例:

Class clazz = String.class;

方式2:获取对象的运行时类型

前提:已知某个类的实例,调用该实例的getClass()方法获取Class对象

实例:

Class clazz = "www.atguigu.com".getClass();

方式3:可以获取编译期间未知的类型

前提:已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName()获取,可能抛出ClassNotFoundException

实例:

Class clazz = Class.forName("java.lang.String");

方式4:其他方式(不做要求)

前提:可以用系统类加载对象或自定义加载器对象加载指定路径下的类型

实例:

ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass("类的全类名");
Class的实例指向结构

简言,所有的Java类型

》class:外部类,成员(成员内部类,静态内部类),局部内部类,匿名内部类

》interface:接口

》[]:数组

》enum:枚举

》annotation:注解@interface

》primitive type :基本数据类型

》void

类的加载过程(了解)

过程1:类的装载(loading)

将类的class文件读入内存,并为之创建一个java.lang.Class对象。此过程由类加载器完成

过程2:链接(linking)

> 验证(Verify):确保加载的类信息符合JVM规范,例如:以cafebabe开头,没有安全方面的问题。

> 准备(Prepare):正式为类变量(static)分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区中进行分配。

> 解析(Resolve):虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。

过程3:初始化(initialization)

执行类构造器<clinit>()方法的过程。

类构造器<clinit>()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。

关于类的加载器(了解、JDK8版本为例)

作用:负责类的加载,并对应于一个Class的实例。

分类(分为两种):

> BootstrapClassLoader:引导类加载器、启动类加载器

> 使用C/C++语言编写的,不能通过Java代码获取其实例

> 负责加载Java的核心库(JAVA_HOME/jre/lib/rt.jar或sun.boot.class.path路径下的内容)

> 继承于ClassLoader的类加载器

> ExtensionClassLoader:扩展类加载器

> 负责加载从java.ext.dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录 下加载类库

> SystemClassLoader/ApplicationClassLoader:系统类加载器、应用程序类加载器

> 我们自定义的类,默认使用的类的加载器。

> 用户自定义类的加载器

> 实现应用的隔离(同一个类在一个应用程序中可以加载多份);数据的加密。

以上的类的加载器是否存在继承关系? No!

使用类的加载器获取流,并读取配置文件信息
/*
* 需求:通过ClassLoader加载指定的配置文件
* */
@Test
public void test3() throws IOException {Properties pros = new Properties();//通过类的加载器读取的文件的默认的路径为:当前module下的src下InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("info1.properties");pros.load(is);String name = pros.getProperty("name");String pwd = pros.getProperty("password");System.out.println(name + ":" +pwd);
}

反射的应用

1. 创建运行时类的对象

如何实现

通过Class的实例调用newInstance()方法即可

且需要满足以下条件:

》要求运行时必须提供一个空参构造器

》要求提供的空参构造器的权限要足够

JavaBean中要求给当前类提供一个公共的的空参的构造器。

作用:

>场景1:子类对象在实例化时,子类的构造器的首行默认调用父类空参构造器

>场景2:在反射中,经常用来创建运行时类的对象。那么我们要求各个运行时类都提供一个空参构造器,便于我们编写创建运行时类对象的代码。

2. 获取运行时类的内部结构

》获取运行时类的内部结构:所有属性、所有方法、所有构造器

》获取运行时类的内部结构:父类、接口、包、带泛型的父类、父类的泛型等

3. 调用指定的结构:指定的属性、方法、构造器

调用指定的属性步骤

步骤1. 通过Class实例调用getDeclareField(String fieldName),获取运行时类指定名的属性

步骤2. setAccessible(true),确保此属性是可以访问的

步骤3. 通过Field类的实例调用get(Object obj)(获取操作)

或set(Object obj,Object value)(设置的操作)进行操作

调用指定的方法步骤

步骤1. 通过Class实例调用getDeclareField(String methodName,Class ... args),获取运行时类指定的方法

步骤2. setAccessible(true),确保此属性是可以访问的

步骤3. 通过Method实例invoke(Object obj,Object .. objs),即为对Method对应方法的调用

invoke()返回值即为Method对应方法的返回值

特别的:如果Method对应的方法的返回值类型为void,则invoke()返回值为null

调用指定的构造器步骤

步骤1. 通过Class的实例调用getDeclaredConstructor(Class ... args),获取指定参数的构造器

步骤2. setAccessible(true):确保此构造器是可访问的

步骤3. 通过Constructor实例调用newInstance(Object ... objs),返回一个运行时类的实例

4. 注解的使用

框架层面

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

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

相关文章

RK3399平台开发系列讲解(内核入门篇)ConfigFS 的核心数据结构

🚀返回专栏总目录 文章目录 一、关键数据结构二、config_item 的结构体三、属性和方法沉淀、分享、成长,让自己和他人都能有所收获!😄 📢虚拟文件系统 ConfigFS 是一个特殊的文件系统,旨在提供一种动态配置 Linux 内核和设备的机制。 一、关键数据结构 ConfigFS 的核…

Vue表单的整体处理

在前端的处理中&#xff0c;表单的处理永远是占高比例的。在BOMDOMjs的时候是这样&#xff0c;在Vue的时候也是这样。Vue的表单处理做了特别的优化&#xff0c;如值绑定、数据验证、错误提示、修饰符等。 表单组件的示例&#xff1a; <script setup lang"ts">…

如何用Postman做接口自动化测试?一文5个步骤带你成功实现!

什么是自动化测试 把人对软件的测试行为转化为由机器执行测试行为的一种实践。 例如GUI自动化测试&#xff0c;模拟人去操作软件界面&#xff0c;把人从简单重复的劳动中解放出来 本质是用代码去测试另一段代码&#xff0c;属于一种软件开发工作&#xff0c;已经开发完成的用例…

解决kubernetes中微服务pod之间调用失败报错connection refused的问题

现象&#xff1a; 从这里可以看到是当前服务在调用product service服务是出现了连接拒绝connection refused 走读一下原始代码&#xff1a; 可以看到请求是由FeignClient代理发出的 &#xff0c;但问题在于为什么Feign请求的时候会产生connection refused错误&#xff1f; 上…

Programming Tensor Cores: NATIVE VOLTA TENSOR CORES WITH CUTLASS

PROGRAMMING TENSOR CORES: NATIVE VOLTA TENSOR CORES WITH CUTLASS 源自于 GTC Silicon Valley-2019: cuTENSOR: High-performance Tensor Operations in CUDA&#xff0c;介绍了 CUTLASS 1.3 中基于 Volta Tensor Core 实现高效矩阵乘法计算的策略。主要内容为以下三点&…

Python函数式编程:让你的代码更优雅更简洁

概要 函数式编程&#xff08;Functional Programming&#xff09;是一种编程范式&#xff0c;它将计算视为函数的求值&#xff0c;并且避免使用可变状态和循环。 函数式编程强调的是函数的计算&#xff0c;而不是它的副作用。 在函数式编程中&#xff0c;函数是第一类公民&a…

【Vue3】解决Vue打包后上传服务器 资源路径加载错误

问题&#xff1a; 我这里在打包Vue之后将打包后的dist 上传至服务器站点根目录内子目录 名为 "adminstore" , 但是当我通过域名打开站点后发现 资源加载路径内并没有携带 子目录 "adminstore" 文件名称 错误&#xff1a;http://your website domain/js/app…

Java 开发常用的 Linux 命令汇总(建议收藏)

虽然平时大部分工作都是和Java相关的开发, 但是每天都会接触Linux系统, 尤其是使用了Mac之后, 每天都是工作在黑色背景的命令行环境中. 自己记忆力不好, 很多有用的Linux命令不能很好的记忆, 现在逐渐总结一下, 以便后续查看. 基本操作 Linux关机,重启 # 关机 shutdown -h n…

面试Java笔试题精选解答

文章目录 热身级别数组中重复的数字思路&#xff1a;使用map或HashSet来遍历一遍就可以找出重复的字符样例解答 用两个栈实现队列思路&#xff1a;Stack1正向进入&#xff0c;队头在栈底&#xff0c;用于进队列操作&#xff1b;Stack2是Stack1倒栈形成&#xff0c;队头在栈顶&a…

学生成绩管理系统(C++实现)

问题描述 实现学生成绩管理系统&#xff1a; 学生信息包括&#xff1a;学号、姓名、性别、年龄、班级等信息。除了包括学生所有信息外&#xff0c;还包括专业、英语、程序设计和高等数学等课程。 设计一程序能够对学生成绩进行管理&#xff0c;应用到继承、抽象类、虚函数、虚…

基于5G+物联网+SaaS+AI的农业大数据综合解决方案:PPT全文44页,附下载

关键词&#xff1a;智慧农业大数据&#xff0c;5G智慧农业&#xff0c;物联网智慧农业&#xff0c;SaaS智慧农业&#xff0c;AI智慧农业&#xff0c;智慧农业大数据平台 一、智慧农业大数据建设背景 1、应对全球人口快速增长带来的粮食生产压力&#xff0c;未来的粮食生产力必…

宣传技能培训1——《新闻摄影技巧》光影魔法:理解不同光线、角度、构图的摄影效果,以及相机实战操作 + 新闻摄影实例讲解

新闻摄影技巧 写在最前面摘要 构图与拍摄角度景别人物表情与叙事远景与特写 构图与拍摄角度案例 主体、陪体、前景、背景强调主体利用前景和背景层次感的创造 探索新闻摄影中的构图技巧基本构图技巧构图技巧的应用实例实例分析1. 黄金分割和九宫格2. 三角型构图3. 引导线构图4.…

1)业务平台集成电子签章平台

1.前言 电子签章平台随着企业数字化转型逐步渗透到日常运营项目中&#xff0c;如合同盖章/规章制度发布/法审意见等场景下引入电子章解决盖章需求。 作为特定业务下的统一处理方案&#xff0c;需要在业务管理平台与电子签章平台之间构建一个桥梁&#xff0c;简化电子签章平台…

Spring配置其他注解Spring注解的解析原理

Spring配置其他注解 Primary注解用于标注相同类型的Bean优先被使用权&#xff0c;Primary是Spring 3.0引入的&#xff0c;与Component和Bean一起使用&#xff0c;标注该Bean的优先级更高&#xff0c;则在通过类型获取Bean或通过Autowired根据类型进行注入时&#xff0c;会选用优…

【C++11并发】future库 笔记

简介 C11之前&#xff0c;主线程要想获取子线程的返回值&#xff0c;一般都是通过全局变量&#xff0c;或者类似机制。C11开始为我们提供了一组方法来获取子线程的返回值&#xff0c;并保证其原子性。 头文件 #include <future>std::promise 在promise中保存了一个值…

Python 的字符串格式化指南

字符串格式化 Python 中控制字符串格式通常有三种形式&#xff1a; % 占位符&#xff08;格式化符&#xff09;str.format() 函数f-string 内嵌式 Python 最先开始格式化字符串是用 %&#xff0c;但它的致命缺点是支持的类型有限制&#xff0c;只支持 int&#xff0c;str&am…

【从零开始实现意图识别】中文对话意图识别详解

前言 意图识别&#xff08;Intent Recognition&#xff09;是自然语言处理&#xff08;NLP&#xff09;中的一个重要任务&#xff0c;它旨在确定用户输入的语句中所表达的意图或目的。简单来说&#xff0c;意图识别就是对用户的话语进行语义理解&#xff0c;以便更好地回答用户…

XUbuntu22.04之解决gpg keyserver receive failed no data(一百九十三)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

DevExpress WinForms TreeMap组件,用嵌套矩形可视化复杂分层数据

DevExpress WinForms TreeMap控件允许用户使用嵌套的矩形来可视化复杂的平面或分层数据结构。 DevExpress WinForms有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。同时能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风…

中文rlhf数据集50w条数据解析

中文rlhf数据集50w条数据解析 解析代码数据名代码解析 解析代码 import jieba from tqdm import tqdm import re import pandas as pd import numpy as npdef find_non_english_text(text):pattern re.compile(r[^a-zA-Z])return pattern.sub(, text)def find_chinese_text(t…