哪个更快,抽象类还是接口?

10

可能是重复问题:
为什么接口方法调用比具体方法调用慢?

最近我有机会参加一次面试,面试官问我在抽象类接口中哪一个更快。虽然我对这个问题感到困惑,但我回答说接口更快,主要是因为我认为晚绑定的概念会导致抽象类的性能延迟。在网上探索了这个问题后,我发现抽象方法更快,尽管根据一些博客的说法,接口方法更快。我有点困惑,所以我想问这个问题,以便正确理解哪一个更快,为什么,并给出充分的理由。

根据以下内容,抽象类很快,但没有合理的原因。 http://www.codeproject.com/Articles/11155/Abstract-Class-versus-Interface

2个回答

12
答案取决于所使用的编程语言和可能的编译器。在像Java虚拟机这样使用运行时优化的环境中,可能根本无法回答这个问题。而且,坦率地说,在典型的Java项目中,没有人关心这个问题,因为即使有差异,也很微小,不会明显减慢软件的速度。除非您有严格的实时约束条件,在这种情况下,您将不使用Java(可能根本不使用多态)。
基本上,接口方法和抽象方法都使用动态分派,因此如果有任何区别,差异是很小的。缺乏对细节的了解,我会假设在类没有实现多重继承的语言中,从理论上讲,抽象方法调度更快。方法指针在分派向量中的位置将是静态的,而对于接口方法来说则不是(一个类通常可以实现多个接口)。
但正如我所说,我不知道编译器中发生了什么。可能还有其他因素我没有考虑到。如果我必须在面试中回答这个问题,我会引用Donald Knuth的“过早优化是万恶之源”。

0

对于这个问题的最佳答案是:“如果我真的需要知道,我会编写一个小测试来找出答案”。在受控条件下使用两个仅在接口与抽象类之间有所不同的实现运行一个真实的示例。没有具体的实现,“哪个更快”的问题就毫无意义了。面试官可能是想炫耀(并且可能对实际答案一无所知),也可能是想测试你的批判性思维能力(这个问题有意义吗?),或者是极端挑剔。

优化的第一条规则是不要优化……至少还不要。第二条规则是在重构之前对程序进行分析以找出瓶颈:正确的算法或数据结构的更改通常是唯一需要的;我敢打赌,在Java中,如果有任何区别,热点编译器将使抽象和接口之间的任何差异真正难以发现。


非常想把第一条规则重复一遍,就像所有那些“搏击俱乐部的第一条规则”引用一样... - tucuxi
1
这种哲学的问题在于它无法揭示现实因素是否会导致一种通常更优越的方法有时表现得比一种通常更劣的方法要差得多。例如,在两个代码片段之间进行选择时,一个需要访问几个四个vtable,而另一个需要分配额外的32字节垃圾,可能会发现生成更多垃圾的那个通常会更快,但如果在gen0收集周期之间触及了大量的gen2垃圾,则可能会变得更慢。 - supercat
1
到处手动优化并不是一个好主意。另一方面,我遇到过这样的情况(VB6“Collection”对象),在基准测试中表现良好的东西开始表现出比N^3更糟糕的行为(其中N是“Collection”对象的总数-而不是任何特定对象的大小!)一旦N达到大约十万个。如果涉及泛型,那么一个“AbstractClass<T>”与一个“Interface<T>”可能会表现出非常不同的行为,特别是如果有许多不同类型的“T”,这并不是不可信的。 - supercat
可能最有帮助的是一个有组织的目录,列出通常表现良好但在某些情况下可能会导致意外性能瓶颈的类型,这样考虑使用它们的人就可以确定他们的预期设计是否会遇到性能瓶颈,如果是,就可以选择另一种方案。对于“XX是否会有任何意外的性能瓶颈”的答案,90%的时间将是“否”,而这些“否”并不是非常有趣或有用的,但是少数的“是”可能非常有趣和有用。 - supercat
O(n³)性能,当n ~= 10⁵时?您应该已经遇到了更小的n;此外,请考虑提交一个错误报告。看起来非常特殊情况下的、实现相关的和难以围绕代码构建的问题。如果Java中出现这样的问题,它很快就会被Oracle或OpenJDK修复;将其视为错误而不是要全面记录下来以供后代使用会更好。 - tucuxi
显示剩余3条评论

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