反射的哪些部分性能不佳?

3

可能重复:
为什么反射很慢?

据说,反射的某些部分性能不是很好。这是真的吗?哪些部分被认为执行缓慢?

背景:我目前正在使用反射实验自己编写的持久化层。我还没有进行任何测量。我只需要知道可能的优化点在哪里,以便我可以设计程序。


不必自己创建持久层,您可以考虑为众多开源持久层之一做出贡献。 - bdoughan
反射相对于什么而言是慢的?除了检查类和对象之外,您还比较了哪些机制? - Jé Queue
5个回答

3

大多数使用反射的框架都会缓存反射操作的结果,以便它们不必再次执行。因此,实际上一切都在启动时发生了一次。

除此之外 - 所有部分都是“低效”的。正常代码应避免使用整个反射API。对于框架-请参见第1段。


你会如何缓存反射创建的对象,例如 Object c = klass.newInstance()? - Aravind Yarram
@Pangea - 当然,创建过程无法缓存。但是所有其他元数据都可以。 - Bozho
谢谢回答。我会考虑缓存我使用的Field对象。 - user573215

3
通常情况下,方法调用工作得很好。性能问题可能是由于Class.getMethod()Class.getField()Class.getDeclaredMethod()等引起的。Class.forName()也很慢(尽管它更像是动态类加载而不是反射)。
因此,我建议您缓存方法定位方法的结果,例如:
Method m = Class.getMethod("foo"); // do it once

// now invoke it as many times as you want

m.invoke(obj);

1
你能演示为什么这些方法会慢吗?我的意思是,Class.getField() 和 Map.get() 基本上做的事情是一样的,但是前者还包括了一些层级遍历,对吧?而 Class.getDeclaredFields 则更简单一些。至于 Method.invoke,我觉得它看起来更加复杂。当然,这只是我的感觉。 - maaartinus
谢谢回答。我使用getDeclaredFields()。也许我会缓存这些字段。等我到那一步时再来测量。 - user573215

0

反射的整个意义在于规避类型系统,以便在语言最初并不打算执行的情况下完成任务。因此,无论你做什么,它都会很慢。

反射允许您在性能上进行权衡,以获得更简单的解决方案,这可以更快速地编写并易于维护。一旦您发现自己在使用反射使代码复杂化时,那么您就是在做错误的事情。

更新

我所说的“更简单”是指更少的代码行数。这基本上是一个更短的解决方案。反射允许您放弃类型安全性,以编写更短、更简洁的程序。这就是动态类型的合理性所在。Java泛型提供了一个更复杂的程序,但您具有类型安全性。反射在静态类型的语言中提供了动态类型。我的观点是,如果“反射”版本的程序比等效的“非反射”版本更复杂,那么非反射版本优于反射版本,因为它将运行更快且更简单。

还有其他用途的反射,但元编程并不是其中之一。元编程是写一个程序来编写另一个程序。例如,假设您想要重新格式化大量文件的名称;也许是一组婚礼照片。执行此操作的程序可能如下所示:

mv "1bill and fred(kfjw0f3).jpg" "1 - bill and fred.jpg"
mv "2sam and kim(g02fsgsg).jpg" "2 - sam and kim.jpg"
.
.
.

一个生成mv命令列表的Ruby程序将是一个元编程程序。

感谢您的回答。我同意第一段的观点。但我不确定您所说的“更简单的解决方案”是什么意思。难道反射不就是元编程的一种吗?这样你就可以创建真正通用的算法了。 - user573215

0

-1

速度主要取决于处理器需要执行多少条指令

(这是一种过度简化,但让我们暂且这么认为吧)。

当您调用一个方法时,代码可以进行JIT编译,从而减少开销。您已经知道将要调用哪个方法,因此您知道是否以有效的方式调用它,它返回什么,它需要什么代码等等。

当您使用反射时,所有这些都变得不确定。您必须尝试使用字符串找到该方法,然后查看是否正确调用它,然后获取所有代码并运行它。通常,这些都无法预先完成。


这涉及到静态和动态之间的区别:

静态:快速,所有内容在执行时都已知,最小化执行时间所需的工作量。

动态:慢,事情稍后才能弄清楚,因此必须在运行时完成一些工作。

这并不意味着反射是“不好”的!速度并不是唯一的考虑因素!

如果它可以节省时间并使事情更简单:那就做吧!如果您后来发现需要更好的性能,并且反射在运行时间的 ~20% 中运行了 ~80%,那么请考虑其他解决方案。如果是这样,Java 将是一种非常不同的语言,您几乎不会使用对象。显然,您应该考虑速度,并对反射有一些了解,这正是您提出这个问题的原因。:D


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接