首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

反射访问属性或方法时将Accessible设置为true

大家好,我是雄雄,欢迎关注公众号【雄雄的小课堂】。

今天给大家分享的是:反射访问属性或方法时将Accessible设置为true。

内容参考自:《编写高质量代码:改善java程序的151个建议》

作者:秦少波

Java中通过反射执行一个方法的过程如下:获取一个方法对象,然后根据isAccessible返回值确定是否能够执行,如果返回值为false则需要调用setAccessible(true),最后再调用invoke执行方法,具体如下:

此段代码已经成为了习惯用法:通过反射方式执行方法时,必须在invoke之前检查Accessible属性。这是一个好习惯,也确实应该如此,但方法对象的Accessible属性并不是用来决定是否可访问的,看如下代码:

定义一个public类的public方法,这是一个没有任何限制的方法,按照我们对Java语言的理解,此时doStuff方法可以被任何一个类访问。我们编写一个客户端类来检查该方法是否可以反射执行:

很简单的反射操作,获得一个方法,然后检查是否可以访问,最后执行方法输出。让我们来猜想一下结果:因为Foo类是public的,方法也是public,全部都是最开放的访问权限,那么Accessible也应该等于true。但是运行结果却是:

为什么Accessible属性会等于false?而且等于false了还能执行?这是因为Accessible的属性并不是我们语法层级理解的访问权限,而是指是否更容易获得,是否进行安全检查。

我们知道,动态修改一个类或方法或执行方法时都会受Java安全体系的制约,而安全的处理是非常消耗资源的(性能非常低),因此对于运行期要执行的方法或要修改的属性就提供了Accessible可选项:由开发者决定是否要逃避安全体系的检查。

阅读源代码是理解的最好方式,我们来看AccessibleObject类的源代码,它提供了取消默认访问控制检查的功能。首先查看isAccessible方法,代码如下:

AccessibleObject是Field、Method、Constructor的父类,决定其是否可以快速访问而不进行访问控制检查,在AccessibleObject类中是以override变量保存该值的,但是具体是否快速执行是在Method类的invoke方法中决定的,代码如下:

看了这段代码,诸位就很清楚了:Accessible属性只是用来判断是否需要进行安全检查的,如果不需要则直接执行,这就可以大幅度地提升系统性能(当然了,由于取消了安全检查,也可以运行private方法、访问private私有属性了)。经过测试,在大量的反射情况下,设置Accessible为true可以提升性能20倍以上。

AccessibleObject的其他两个子类Field和Constructor与Method的情形相似:Accessible属性决定Field和Constructor是否受访问控制检查。我们在设置Field或执行Constructor时,务必要设置Accessible为true,这并不仅仅是因为操作习惯的问题,还是在为我们系统的性能考虑。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20210209A00ROR00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券