抽象类比Java中的接口快吗?

时间:2018-06-30 08:00:06

标签: java jvm

根据本文here,在抽象类与接口上,抽象类比接口要快一点,为什么这样做呢?您能否根据JVM来解释使用接口与抽象类的机制?

  

4)Java中抽象类和接口之间的第四个区别   是抽象类比接口快一点,因为   介面会在呼叫中的任何覆写方法之前先进行搜寻   Java。在大多数情况下,这并不是显着差异,但是如果   您正在编写时间紧迫的应用程序,那么您可能不想   坚不可摧。

2 个答案:

答案 0 :(得分:5)

在Java的早期,存在技术上的差异。您知道什么是“虚拟表”或“ vtbl”吗?基本上,一个简单的vtbl可以用于直接继承的方法,因此JVM只需要查看两个指针即可找到从抽象类继承的方法的代码-相对来说比较快。但是,由于任何类都可以实现任意数量的接口,因此找到实现接口方法的代码将涉及跟踪指向由类实现的接口表的指针,然后在该表中进行搜索以找到用于该接口实现的vtbl,然后在表中找到方法指针。显然,这需要做很多工作,因此调用接口方法通常要慢得多。

如今,JVM变得更加智能,并且大多数此类查找是在动态编译期间完成的,因此运行时差异很小或根本不存在。

答案 1 :(得分:3)

答案取决于实现细节,但是以这种形式,这是不正确的。实际上,作者确实已经尝试通过使用“轻微”一词来躲避事实检查,以免您从未观察到这种性能差异。

this answer所述,该语句背后的想法是,普通类具有可重写方法的表(也称为“ vtable”),该表由子类继承,可以在子类中添加新方法。结束并替换其替代方法的表条目。因此,第一个解决方案只需要找到表索引即可记住,因此后续调用仅需要在该索引处调用实际接收器类的方法。

由于接口可以由不具有继承关系的不同类实现,因此这些类的实现方法可能位于不同的表索引处。解决此问题的一种方法是,将接口的表映射到实际的类的表。假设这种双重调度会导致这样的假设,即调用接口方法比普通方法慢。

但是,像HotSpot JVM这样的JVM不使用这种双重调度。它们像其他任何虚拟方法调用一样,针对实际的接收器类解析接口方法调用。例如,只要接收方是同一类层次结构的一部分,就可以在Appendable接口上调用一个方法,并且接收方始终是Writer类的子类,则不需要其他步骤。对于大多数所有接口方法调用,此方法都很好。

在某些情况下,接口方法调用最终会在不相关类的不同实现上结束,例如,Appendable方法的调用有时会在StringBuilder上结束,而其他时候会在{{ 1}},但是接下来,我们有一个无法比拟的场景。这种特定的调用可能比普通的方法调用稍慢一些,但是由于不可能用抽象类来构造相同的场景,因此在这里说它比使用抽象类要慢是没有任何意义的。

对于与性能相关的代码部分(也称为热点),JVM将执行运行时优化,这将使这种技术差异始终无关紧要。通常,即使是普通虚拟方法调用的一小笔开销也通常会被消除,因为随后的优化很大程度上依赖于积极内联目标方法代码的能力,以便能够使用调用方的上下文及其已知的周围条件来优化目标方法。被叫方的代码。