java反射为什么慢?

这个问题是从《think in java 第一章 对象入门》中引出来的,我之前思考了一下为什么要使用接口,然后发现有这样一种说法:接口也是实现给编译器看的,如果没有接口,加载类的时候就要使用反射去获取类中的方法和属性了,这样效率很差。

这就引出了一个问题了,我们都知道反射慢,不如直接new的效率高,那为什么反射会如慢呢?我很想搞清楚为什么…

 

网上大多都是对于反射用法的介绍,但是对于原理层面则没有太多涉及…

以下是我从网上找到的一些回答:

1.stackoverflow上的高赞回答

很多人的根据都引用了这个回答

qq%e6%88%aa%e5%9b%be20161209112130

这个答案感觉回答得很全面:

1.因为不知道你正在做什么,所以编译器没有办法帮你做优化,导致了编译速度变慢。

2.所有被注入和创建的东西首先要被找到。类根据类名称,方法根据匹配。

3.参数需要被装拆箱,有一系列的检查机制。

4.整个反射的创建流程如下:

2

总之,与直接实例化对象想比,反射是一个很复杂的过程。

如果我们使用反射方法实例化对象,从表面上看,似乎只需要简单几步就够了。其实这“简单几步”背后存在非常复杂的处理,导致反射更“慢”。

但是,这个回答者同时提到了:我们不要太纠结于反射的“慢”,用就好了。

1.很多ide大量使用了反射技术,然而运行起来并不慢。而且这个“慢”是相对的对于机器来说的慢,但是对人来说已经足够快了。

2.反射的效率问题在分析xml和读取数据库问题上是小巫见大巫。

2.参数检查的情况

慢的原因还有安全检查,访问控制等。比如说这个方法你能不能获得,能不能执行等,你传进的参数的类型检查等。
比如说在使用反射调用方法的时候,传进的参数需要检查是否符合方法参数类型要求吧?
可以通过缓存一些方法来提高速度和性能。

3.查找过程

如果你每次调用都靠反射,每次都要靠名字去查找对应方法,这个查找本身是最慢的。说不慢的朋友拿反射调用和直接调用的速度比比看就知道了。

对于这个说法,我写了个程序验证了一下:

结果是

后来我才看到一片专门去测反射效率的文章,那篇文章中的效率差得没我这个这么多…

有兴趣可以看看:https://zhuanlan.zhihu.com/p/21435008

后来才发现这种测试方式不科学,测试的并不是真正的结果。具体原因在jvm不会去优化反射的代码,但是会优化非反射的部分,所以导致差距特别明显。真实环境下jvm未必能对代码进行优化,在这种情况下测试的数据才是有参考价值的。

详情见:http://blog.csdn.net/lzljs3620320/article/details/51111112

4.借用R大的语录进行总结

Method.invoke()本身要用数组包装参数。每次调用invoke()都必须检查方法的可见性,也必须检查每个实际参数与形式参数的类型匹配性(一系列的检查机制需要耗时)。

反射使得JIT编译器无法有效做优化确实是反射慢的主要原因(编译器优化的效果可能不佳)。

5.总结

看了这么多人的解释,反射比直接调用更加影响速度,这是肯定的。灵活性当然要牺牲性能,但是基本构不成什么大问题。比起反射带来的好处,这种牺牲可以接受。

而且什么依赖注入,动态代理什么的,不依赖反射根本没办法实现,所以大胆使用吧。

发表评论

电子邮件地址不会被公开。 必填项已用*标注