前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java反射的二三事

java反射的二三事

作者头像
lyb-geek
发布2018-03-27 14:39:41
7100
发布2018-03-27 14:39:41
举报
文章被收录于专栏:Linyb极客之路

一、什么是反射机制

简单的来说,反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息,诸如:类变量,构造函数,方法,修饰符。

二、反射机制的优点与缺点

优点:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多 态的应用,有以降低类之间的藕合性。

缺点:对性能有影响

三、利用反射机制能获得什么信息

一句话,类中有什么信息,它就可以获得什么信息,不过前提是得知道类的名字,要不就没有后文了

首先得根据传入的类的全名来创建Class对象。

Class c=Class.forName("className");注明:className必须为全名,也就是得包含包名,比如,cn.netjava.pojo.UserInfo;

Object obj=c.newInstance();//创建对象的实例

OK,有了对象就什么都好办了,想要什么信息就有什么信息了。

获得构造函数的方法

Constructor getConstructor(Class[] params)//根据指定参数获得public构造器

Constructor[] getConstructors()//获得public的所有构造器

Constructor getDeclaredConstructor(Class[] params)//根据指定参数获得public和非public的构造器

Constructor[] getDeclaredConstructors()//获得public的所有构造器

获得类方法的方法

Method getMethod(String name, Class[] params),根据方法名,参数类型获得方法

Method[] getMethods()//获得所有的public方法

Method getDeclaredMethod(String name, Class[] params)//根据方法名和参数类型,获得public和非public的方法

Method[] getDeclaredMethods()//获得所以的public和非public方法

获得类中属性的方法

Field getField(String name)//根据变量名得到相应的public变量

Field[] getFields()//获得类中所以public的方法

Field getDeclaredField(String name)//根据方法名获得public和非public变量

Field[] getDeclaredFields()//获得类中所有的public和非public方法

四、反射适用场景

1、Java的反射机制在做基础框架的时候非常有用,有一句话这么说来着:反射机制是很多Java框架的基石,而一般应用层面很少用。

2.当你做一个软件可以安装插件的功能,你连插件的类型名称都不知道,你怎么实例化这个对象呢?因为程序是支持插件的(第三方的),在开发的时候并不知道 。所以无法在代码中 New出来 ,但反射可以,通过反射,动态加载程序集,然后读出类,检查标记之后再实例化对象,就可以获得正确的类实例。

3.在编码阶段不知道那个类名,要在运行期从配置文件读取类名, 这时候就没有办法硬编码new ClassName(),而必须用到反射才能创建这个对象.反射的目的就是为了扩展未知的应用。比如你写了一个程序,这个程序定义了一些接口,只要实现了这些接口的dll都可以作为插件来插入到这个程序中。那么怎么实现呢?就可以通过反射来实现。就是把dll加载进内存,然后通过反射的方式来调用dll中的方法。很多工厂模式就是使用的反射。

五、反射影响性能的原因

反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多,其次由于反射是本地方法调用,让JVM无法优化,反射方法调用还有验证过程和参数问题,参数需要装箱拆箱、需要组装成Object[]形式、异常的包装等等问题。。。

六、反射性能优化

1、setAccessible(true)

使用了method.setAccessible(true)后 性能有了20倍的提升,实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问,由于JDK的安全检查耗时较多.所以通过setAccessible(true)的方式关闭安全检查就可以达到提升反射速度的目的

JDK API中的解释 :

AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。它提供了将反射的对象标记为在使用时取消默认 Java 语言访问控制检查的能力。对于公共成员、默认(打包)访问成员、受保护成员和私有成员,在分别使用 Field、Method 或 Constructor 对象来设置或获得字段、调用方法,或者创建和初始化类的新实例的时候,会执行访问检查。

在反射对象中设置 accessible 标志允许具有足够特权的复杂应用程序(比如 Java Object Serialization 或其他持久性机制)以某种通常禁止使用的方式来操作对象。

2、jit,不去了解反射优化,还真不知道JIT是什么东西

如果你在jdk6上跑,且如果你反射的目标方法是getter/setter methods的话,记得加上配置:-XX:-UseFastEmptyMethods -XX:-UseFastAccessorMethods , 这两个配置的关闭是为了让accessor methods能够被jit; jdk7以上不需要设置这两个配置

即时编译,又译及时编译、实时编译,动态编译的一种形式,是一种提高程序运行效率的方法。通常,程序有两种运行方式:静态编译与动态直译。静态编译的程序在执行前全部被翻译为机器码,而直译执行的则是一句一句边运行边翻译。 即时编译器则混合了这二者,一句一句编译源代码,但是会将翻译过的代码缓存起来以降低性能损耗。相对于静态编译代码,即时编译的代码可以处理延迟绑定并增强安全性。 即时编译器有两种类型,一是字节码翻译,二是动态编译翻译。 微软的.NET Framework,还有绝大多数的Java实现,都依赖即时翻译以提供高速的代码执行

如果你在jdk6上跑,且如果你反射的目标方法是getter/setter methods的话,记得加上配置:-XX:-UseFastEmptyMethods -XX:-UseFastAccessorMethods , 这两个配置的关闭是为了让accessor methods能够被jit; jdk7以上不需要设置这两个配置

3、缓存(推荐使用org.codehaus.groovy.reflection.ReflectionCache这个类)

该类在类库groovy-all-2.4.6.jar可以找到

这个优化是一般反射优化的基本解决方案,就是把所有经常用到的反射对象缓存起来,在下次用到的时候直接从缓存中获取。

4.系统启动阶段使用反射。

将反射得到元数据保存起来,使用时,只需从内存中调用即可,hotspot虚拟机会对执行次数较多的方法进行优化(例如使用jit技术)

5、使用高性能的反射类库ReflectASM(该类库无法反射私有方法和变量)

另外也推荐spring自带的ReflectionUtils工具类

章后建议:在业务开发时尽量远离反射,首先是代码可读性与工具支持。打开熟悉的IDE,寻找你的Java代码的内部依赖,很容易吧。现在,使用反射来替换掉你的代码然后再试一下,结果如何呢?如果通过反射来修改已经封装好的对象状态,那么结果将会变得更加不可控。其次JIT对反射的优化程度是不同的,有些优化时间会更长一些,而有些甚至是无法应用优化。因此,有时反射的性能损失可以达到几个数量级的差别。最后我觉得在业务代码中能合理(直接)使用反射的场景是通过AOP

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-02-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档