【从零到Offer】反射那些事

这篇具有很好参考价值的文章主要介绍了【从零到Offer】反射那些事。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

什么是反射?

​ 反射简单来说,就是在代码运行期间,通过动态指定任意一个类,从而构建对象,并了解该类的成员变量和方法,甚至可以调用任意一个对象的属性和方法。以String对象为例子,传统构造方式和反射的实现方式如下:

//new 构造方法
String s = new String();

//反射
Class<?> forName = Class.forName("java.lang.String");

​ 从代码中不难看到,第一种通过构造函数构造出来的对象,是在编译前就确定好了的。由此编译程序可以明确的知道当前操作的类是哪个,包含哪些属性、有什么方法。

​ 然而对于第二种实现方式来说,通过反射映射出来的对象完全取决于你给定的字符串是什么。如果我们将这个字符串抽取成配置,那么生产出来的对象自然就会是动态的了。

为什么需要反射?

​ 那么,你可能想问了,好好的new 对象不好吗?为啥还要设计出来一个反射呀?他有什么好处呢?其实,直白来讲,反射牺牲掉了安全、效率,更多的是为了提供更多的灵活性。

​ 假设当前你所负责的代码,要处理两个不同的对象,那么为了完成工作,你可能需要通过多次的if-else判断、处理,哪怕两个对象内的字段名称、类型都是一样的,受限于编译器的限制,你也没法共用同一段代码。

if (i==1){
    // ....执行针对ObjectA的处理方法
    ObjectA o = (ObjectA) input;
    o.setData(xxx);
} else if (i==2) {
    // ....执行针对ObjectB的处理方法
    ObjectB o = (ObjectB) input; 
    o.setData(xxx);
}

​ 但是如果借助于反射,我们就可以将代码充分利用起来,从而最大程度减少代码开发,提升日常效率

if (i==1){
    // ....执行针对ObjectA的处理方法
    Class<?> forName = Class.forName("com.example.demo.base.dto.ObjectA");
} else if (i==2) {
    // ....执行针对ObjectB的处理方法
    Class<?> forName = Class.forName("com.example.demo.base.dto.ObjectB");
}       
Object o = (Object) input;

//同一段处理逻辑,无需再写两次
Field resultStr = forName.getDeclaredField("resultStr");
resultStr.set(o, "1");

​ 在日常代码开发中,也有很多组件无形之中使用到了反射的设计原理。如我们熟悉的Bean拷贝组件BeanUtils,其方便的实现对象间的拷贝逻辑就是基于反射实现的。

如何实现反射?

​ 首先我们知道,我们日常所编写的代码,最后都是会变成.java格式的文档。而.java格式的文档是不可能被机器直接执行的,因为机器只能够看懂二进制的文件。

​ 因此,从.java文件到jvm中可执行的对象,它其实经过了如下的过程:

【从零到Offer】反射那些事,开发语言,java,spring boot

​ 首先,我们的.java文件会被编译器编译成.class文件,对于每个.class文件,又会被JVM调用类加载的方式,加载到JVM内存中并生成为一个Class对象。这里我们简单看一下Class对象长什么模样:

【从零到Offer】反射那些事,开发语言,java,spring boot

​ 可以看到Class类对象中包含了许多用于描述类的属性,如类名、所使用的类加载器等。包括通过Class类对象也可以搜索到当前类的构造器、特定的属性域等。

​ 而且对于这个特殊的类来说,我们是不能够对其进行初始化的。可以看到,它只提供了一个私有的构造方法,且需要传入的是类加载器。而且在方法的注释上,也很明确的标注出来,这个构造方法只是提供给JVM创建实例用的,不应该作为默认的类构造器。

【从零到Offer】反射那些事,开发语言,java,spring boot

​ 通常来说,如果我们需要调用一个Class对象,那么通常只能通过以下的方式:

Class<?> clz = Class.forName("xxx.class");
Class<?> clz = Object.class;
Class<?> clz = Object.getClass();

​ 而且通过不断的往下搜索,我们也可以看到,这个方法的底层实现是通过native方法实现的。(部分java代码通过c等语言实现的,此时会被标记为native方法,是不可以直接调用的。)

【从零到Offer】反射那些事,开发语言,java,spring boot

​ 虽然我们不能调用,但是本质上这个方法就是通过类加载器获取的过程。了解了这些之后,我们再将咱们的日常使用java类的过程梳理一下:

【从零到Offer】反射那些事,开发语言,java,spring boot

​ 所以可以看到,反射本质上,维护实例的流程同正常的new创建对象并无过多的差异,他们本质都是基于class对象生成的实例,只是通过new的方式,用户是能够明确知道所需要使用的类的,因此编译器也能方便的对代码进行检查。

​ 而使用反射的方式,则是利用了Class对象,创造出了编码的灵活性。本质思想就是:“你可以是任何类,但我的逻辑对任何类都适配。”通过这样的牺牲掉一些安全性,从而获得编码的灵活性。

参考文献

学习java应该如何理解反射?

java的反射到底是有什么用处?怎么用?文章来源地址https://www.toymoban.com/news/detail-575074.html

到了这里,关于【从零到Offer】反射那些事的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【完整版】Eclipse开发环境配置,从零到项目运行

    【完整版】Eclipse开发环境配置,从零到项目运行 1、java环境 安装 本系统使用java6开发,老师使用1.6.0 _45版本开发,如下图所示: “开发工具”目录提供了1.6.0 _45版本32位和64位两个安装程序,大家根据自己电脑操作系统进行选择。 双击运行1.6.0 _45安装程序在自己的电脑上安

    2024年02月08日
    浏览(55)
  • UI/UX设计与前端开发:从零到一打造完美用户体验

    在当今的软件开发领域,UI/UX设计和前端开发是两个密不可分的环节。UI/UX设计师负责创造出直观、美观、用户友好的界面,而前端开发者则将这些设计转化为实际的、可交互的网页或应用。本文将深入探讨这两个领域的交集,并通过代码示例来展示如何实现出色的用户体验。

    2024年02月11日
    浏览(57)
  • 【从零开始学习JAVA | 第四十五篇】反射

    目录 前言: ​反射:  使用反射的步骤: 1.获取阶段: 2.使用阶段: 反射的应用场景: 使用反射的优缺点: 总结: Java中的反射是一项强大而灵活的功能,它允许程序在运行时 动态地获取、操作和利用类的信息 。通过反射,我们可以在运行时检查和修改类的属性、调用类

    2024年02月13日
    浏览(62)
  • “从零开始学习Spring Boot:快速搭建Java后端开发环境“

    标题:从零开始学习Spring Boot:快速搭建Java后端开发环境 摘要:本文将介绍如何从零开始学习Spring Boot,并详细讲解如何快速搭建Java后端开发环境。通过本文的指导,您将能够快速搭建一个基于Spring Boot的Java后端开发环境并开始编写代码。 正文: 一、准备工作 在开始之前,

    2024年02月15日
    浏览(58)
  • 从零开始学习 Java:简单易懂的入门指南之反射(三十八)

    ​ 专业的解释: ​ 是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; ​ 对于任意一个对象,都能够调用它的任意属性和方法; ​ 这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。 ​ 通俗的理解: 利用 反射 创建的对象 可

    2024年02月08日
    浏览(49)
  • JVM:从零到入门

    JVM,就是Java虚拟机。 JVM是一个巨大的话题,我们本文主要简单介绍一些围绕JVM相关的基础知识。 目录 JVM内存区域划分 本地方法栈 虚拟机栈 堆 程序计数器 方法区/ 元数据区 类加载 1.加载 2.验证 3.准备 4.解析 5.初始化 双亲委派模型 垃圾回收机制 引用计数 可达性分析 如何

    2024年01月17日
    浏览(41)
  • Python从零到一构建项目

    随着互联网的发展,网络上的信息量急剧增长,而获取、整理和分析这些信息对于很多人来说是一项艰巨的任务。而Python作为一种功能强大的编程语言,它的爬虫能力使得我们能够自动化地从网页中获取数据,大大提高了效率。本文将分享如何从零到一构建一个简单的网络爬

    2024年02月09日
    浏览(62)
  • 从零到一发布 NPM 包

    如果你负责前端的基础能力建设,发布各种功能/插件包犹如家常便饭,所以熟悉对 npm 包的发布与管理是非常有必要的,故此有了本篇总结文章。本篇文章一方面总结,一方面向社区贡献开箱即用的 npm 开发、编译、发布、调试模板,希望帮助到有需要的同学。 辛苦整理良久

    2023年04月08日
    浏览(53)
  • c# 从零到精通 for语句

    c# 从零到精通 for语句 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test08 { class Program { static void Main(string[] args) { int[] myint = new int[10]; //声明一个具有10个元素的整型数组 myint[0] = 0; //向数组中添加第一个元素 myint[1] = 1; //向数组中添加第二个元素 my

    2024年02月08日
    浏览(49)
  • c# 从零到精通-封装一个类

    c# 从零到精通-封装一个类 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test05 { /// /// 自定义类,封装加数和被加数属性 /// class MyClass { private int x = 0; //定义int型变量,作为加数 private int y = 0; //定义int型变量,作为被加数 /// /// 加数 /// public int X {

    2024年02月08日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包