2010-08-17 156 views
21

是因为我们应该加载类(例如,通过string),创建实例,然后搜索适当的方法,打包参数,然后调用方法?所以大部分时间都花在这些操作上,而不是在对象上显式调用方法,对吧?为什么反射速度很慢?

+3

在现代的jdk/jvm实现中,它并没有你想象的那么慢。 – Roman 2010-08-17 13:08:52

回答

28

您每次使用反射时都需要验证每一步操作。例如,当你调用一个方法时,它需要检查目标是否实际上是方法声明器的一个实例,是否有合适的参数个数,每个参数是否是正确类型等。

绝对没有内联或其他表演技巧的可能性。

如果您通过名称查找类型或方法,那么最好包含一个简单的地图查找 - 每次执行时都会执行该查找,而不是在JIT时间执行一次。

基本上还有很多事情要做。然而,反思比以前快得多,如果你发现它太慢,你可能会过度使用它。

+1

另一个微妙的问题是,在使用反射时,可能需要将混淆器设置为较不积极,从而减少收益。(许多混淆器制造商声称混淆提供了性能优势以及知识产权保护和减少占用空间。请参见,例如[本文](http://www.devx.com/wireless/Article/28989/1954)。) – 2011-11-18 15:21:48

+0

它只是调用,特别慢?其他反射使用如枚举属性,获取声明类型,获取getter/setter方法等?这些也很慢吗? – 2015-06-19 05:54:14

+0

@zespri:那么,“慢”通常是相对于别的东西 - 很难说枚举属性是否是“慢”,因为这不是在反射之​​外完成的 - 而“调用方法”或“获取字段值”很多反射比直接慢。是否仅反射操作比您的应用程序需要它们慢是另一回事... – 2015-06-19 05:59:17

6

作为附录乔恩斯基特的回答以上(我需要更多的声誉,以便能够发表评论。):

反射取决于CPU资源可;如果您的应用程序运行缓慢,则反射无法解决任何问题,只需将其缓慢。

像Java本身,反思不慢任何 - 它更多的是一个古老的传言;)

+0

反思不慢不是真的。 对于三个可放大的类,toString()比手动编码toString要慢百分之五十。 (我正在使用OpenJDK 8) – 2015-06-22 09:17:18

2

当你调用一个方法,你需要知道,如果你用有效的论据这样做,对一个有效的对象,返回类型是什么,以及要执行的字节码。当在代码中指定确切的方法时,java可以快速找出这些东西,然后继续实际执行该方法。

当你用反射来做这件事时,你知道的少得多。由于代码中未指定要调用的方法,因此这些操作都不能事先完成,并且VM必须在运行时执行更加复杂且处理器密集的任务。

多态方法调用虽然可以介于这两个极端之间的某处。在运行时间之前,您不知道要调用什么方法,但至少可以确定方法的名称,参数和返回类型。对于执行什么方法知道的越多,Java在运行时就可以避免的越多。

这证明反射是较慢,但并不是说它实际上是“慢”。如果您需要反射或多态方法,请使用它们,并稍后保存对“慢”的判断。

0

如果以适当的方式使用它,速度并不慢。例如,我用它来扫描模型类中的所有属性,它完美地工作。

在其他情况下,如检查目标是否具有相同的类型或签名,它是非常缓慢的。

事情有时会很慢,但对于开箱即用的实施很重要......:D。