Java反射

字节探云人
• 阅读 274

1 背景

前段时间组内针对“拷贝实例属性是应该用BeanUtils.copyProperties()还是MapStruct”这个问题进行了一次激烈的battle。支持MapStruct的同学给出了他嫌弃BeanUtils的理由:因为用了反射,所以慢。这个理由一下子拉回了我遥远的记忆,在我刚开始了解反射这个Java特性的时候,几乎看到的每一篇文章都会有“Java反射不能频繁使用”、“反射影响性能”之类的话语,当时只是当一个结论记下了这些话,却没有深究过为什么,所以正好借此机会来探究一下Java反射的代码。

2 反射

包结构梳理反射相关的代码主要在jdk rt.jar下的java.lang.reflect包下,还有一些相关类在其他包路径下,这里先按下不表。按照继承和实现的关系先简单划分下java.lang.reflect包:① Constructor、Method、Field三个类型分别可以描述实例的构造方法、普通方法和字段。三种类型都直接或间接继承了AccessibleObject这个类型,此类型里主要定义两种方法,一种是通用的、对访问权限进行处理的方法,第二种是可供继承重写的、与注解相关的方法。
Java反射
② 只看选中的五种类型,我们平常所用到的普通类型,譬如Integer、String,又或者是我们自定义的类型,都可以用Class类型的实例来表示。Java引入泛型之后,在JDK1.5中扩充了其他四种类型,用于泛型的表示。分别是ParameterizedType(参数化类型)、WildcardType(通配符类型)、TypeVariable(类型变量)、GenericArrayType(泛型数组)。
Java反射
③ 与②中描述的五种基本类型对应,下图这五个接口/类分别用来表示五种基本类型的注解相关数据。
Java反射
④ 下图为实现动态代理的相关类与接口。java.lang.reflect.Proxy主要是利用反射的一些方法获取代理类的类对象,获取其构造方法,由此构造出一个实例。java.lang.reflect.InvocationHandler是代理类需要实现的接口,由代理类实现接口内的invoke方法,此方法会负责代理流程和被代理流程的执行顺序组织。
Java反射

Java反射

3 目标

类实例的构造源码以String类的对象实例化为例,看一下反射是如何进行对象实例化的。Class<?> clz = Class.forName("java.lang.String");

String s =(String)clz.newInstance();
Class对象的构造由native方法完成,以java.lang.String类为例,先看看构造好的Class对象都有哪些属性:
Java反射
可以看到目前只有name一个属性有值,其余属性暂时都是null或者默认值的状态。下图是 clz.newInstance() 方法逻辑的流程图,接下来对其中主要的两个方法进行说明:
Java反射
从上图可以看出整个流程有两个核心部分。因为通常情况下,对象的构造都需要依靠类里的构造方法来实现,所以第一部分就是拿到目标类对应的Constructor对象;第二部分就是利用Constructor对象,构造目标类的实例。3.1 获取Constructor对象首先上一张Constructor对象的属性图:
Java反射
java.lang.Class#getConstructor0此方法中主要做的工作是首先拿到目标类的Constructor实例数组(主要由native方法实现),数组里每一个对象都代表了目标类的一个构造方法。然后对数组进行遍历,根据方法入参提供的parameterTypes,找到符合的Constructor对象,然后重新创造一个Constructor对象,属性值与原Constructor一致(称为副本Constructor),并且副本Constructor的属性 root 指向源Constructor,相当于对源Constructor对象进行了一层封装。由于在getConstructor0()方法将返回值返回给调用方之后,调用方在后续的流程里进行了constructor.setAccesssible(true)的操作,这个方法的作用是关闭对constructor这个对象访问时的Java语言访问检查。语言访问检查是个耗时的操作,所以合理猜测是为了提高反射性能关闭了这个检查,又出于安全考虑,所以将最原始的对象进行了封装。

private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
                                    int which) throws NoSuchMethodException
{
//1、拿到Constructor实例数组并进行筛选
    Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC));
 //2、通过对入参的比较筛选出符合条件的Constructor
    for (Constructor<T> constructor : constructors) {
        if (arrayContentsEq(parameterTypes,
                            constructor.getParameterTypes())) {
//3、创建副本Constructor
            return getReflectionFactory().copyConstructor(constructor);
        }
    }
    throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes));
}
点赞
收藏
评论区
推荐文章
捉虫大师 捉虫大师
3年前
我在组内的Nacos分享
本文已收录https://github.com/lkxiaolou/lkxiaolou欢迎star。Nacos简介Nacos:NamingandConfigurationService,可打包部署配置中心和注册中心,也可独立部署其中之一,配置中心、控制台依赖mysql,由阿里巴巴2018年8月开源,github19.1kstar(截止20
Wesley13 Wesley13
3年前
java反序列化——apache
看了好久的文章才开始分析调试java的cc链,这个链算是java反序列化漏洞里的基础了。分析调试的shiro也是直接使用了cc链。首先先了解一些java的反射机制。一、什么是反射反射是Java的特征之一,是一种间接操作目标对象的机制,核心是JVM在运行的时候才动态加载类,并且对于任意一个类,都能够知道这个类的所有属性和方法,调用方法/访问属性
Easter79 Easter79
3年前
springboot2之优雅处理返回值
前言最近项目组有个老项目要进行前后端分离改造,应前端同学的要求,其后端提供的返回值格式需形如{"status":0,"message":"success","data":{}}方便前端数据处理。要实现前端同学这个需求,其实也挺简单的,
御弟哥哥 御弟哥哥
4年前
Java基础与提高干货系列 -- Java反射机制
前言今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来。那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现。正文Java反射机制定义Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性
Wesley13 Wesley13
3年前
C#进阶之路(七)反射的应用
反射在C中的应用还是很多的,但它对代码的性能有一定影响。反射的性能:  使用反射来调用类型或者触发方法,或者访问一个字段或者属性时clr需要做更多的工作:校验参数,检查权限等等,所以速度是非常慢的。所以尽量不要使用反射进行编程,对于打算编写一个动态构造类型(晚绑定)的应用程序,可以采取以下的几种方式进行代替:1、通过类的继承关系。让该
Wesley13 Wesley13
3年前
Java反射技术概述
1.什么是Java反射?  就是正在运行,动态获取这个类的所有信息2.反射机制的作用  a.反编译:.class.java  b.通过反射机制,访问Java对象的属性,方法,构造方法等3.反射机制的应用场景  Jdbc加载驱动  SpringIOC实现  Java框架4.创建对象的两种方式  a.直
可莉 可莉
3年前
15张图带你彻底明白spring循环依赖,再也不用怕了
1.由同事抛的一个问题开始最近项目组的一个同事遇到了一个问题,问我的意见,一下子引起的我的兴趣,因为这个问题我也是第一次遇到。平时自认为对spring循环依赖问题还是比较了解的,直到遇到这个和后面的几个问题后,重新刷新了我的认识。我们先看看当时出问题的代码片段:@ServicepublicclassTestServic
Wesley13 Wesley13
3年前
Java反射机制及适用场景
什么是Java反射机制?JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的以及动态调用对象的方法的功能称为Java的反射机制。反射的适用场景是什么?1.当你做一个软件可以安装插件的功能,你连插件的类型名称都不知道,你怎么实例化这个对象呢
Java反射源码学习之旅 | 京东云技术团队
在我刚开始了解反射这个Java特性的时候,几乎看到的每一篇文章都会有“Java反射不能频繁使用”、“反射影响性能”之类的话语,当时只是当一个结论记下了这些话,却没有深究过为什么,所以正好借此机会来探究一下Java反射的代码。
深入理解java反射机制及应用 | 京东物流技术团队
因为最近项目中经常有java反射的使用,而其中的IOC、动态代理用到了反射,因此趁这个机会来总结一下关于Java反射的一些知识,复习一下。本篇基于JDK1.8。java反射机制是什么反射原理Java反射机制(JavaReflection)是Java的特征之
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(