instanceof 操作符会产生很多开销吗?为什么?

6

我在项目中有一个同事,他强烈反对使用 instanceof 运算符,因为它会“产生很多开销”,这是为什么呢?这是真的吗?

除了使用 instanceof,还有其他方法可以检查对象的类型吗?

因为在某些情况下,我发现它非常有用。


1
我非常怀疑这一点,因为它是一个关键字,编译器通常可以对类型进行静态推断,即使不能,它只需要从某个加载的类表中读取,以查看当前类是否是子类。 - gub
5个回答

15

它确实会产生一些开销,再加上后续的强制类型转换。在最新版本的Java中,这种开销已经减少了。但无论如何,这只是微小优化——也就是说,在一般情况下,您不必担心它。

instanceof 的真正争议点是,在许多情况下,有更好的面向对象编程方式来实现所需的行为。


@Bozho,你能提供一种替代instanceof的方法吗?这种方法可以减少开销。 - Deepak
@Deepak - 多态性。访问者模式有时候。 - Bozho
@Bozho,你有没有任何工作示例可以展示instanceOf确实产生了开销。我该如何模拟它以对抗多态行为? - Deepak
@Bozho,实际上,如果真的只是考虑纯的开销(不建议任何人这样做),当目标类超过2个时,多态性可能会比instanceof生成更多的开销。更多阅读:http://www.azulsystems.com/blog/cliff-click/2010-04-08-inline-caches-and-call-site-optimization - bestsss
1
各位,请不要考虑这样的优化,编译器已经非常擅长优化代码了。除非你能够完全确定微基准测试可能会遭受何种优化,否则请不要编写微基准测试进行测试。 - bestsss
显示剩余2条评论

3

如果编译器可以证明实例,则可能不会产生任何开销。即使编译器无法立即证明目标,开销也非常小。几个 CPU 时钟(特别是如果 instanceof 跳转被正确预测)。

instanceof 后的以下强制类型转换通常是免费的。

(注意:我指的是 JIT 编译器)


:) 拥有比我需要的声誉更多,所以如果愿意的话,大家可以纠正拼写错误和错误。我倾向于在社区维基下发布,除非我忘记了。顺便说一句,根据我的记忆,对于没有子类的类(如Long/Double/String/URL等),instanceof操作符可能只需要一个CPU时钟周期这么廉价。 - bestsss
人们仍然可以编辑您的帖子。所以请放心发布常规答案 ;) - Bozho
不,你需要相当高的声望才能这样做,很少有人敢尝试。声望被过分评价了 :) - bestsss
您无论信誉如何都可以建议编辑。 - Bozho

2
实际上,instanceof返回true和对此类型的强制转换成功并不完全等价 - 后者可能在前者返回false时成功。因此,即使有这样的情况,
String s = someMethodReturningString();
Object o = s;
if (o instanceof String) {
   ...
}

编译器在这里必须生成至少一个检查o!= null

实际上,这是可以忽略不计的。


不想争论,但你是如何将整数赋值给字符串的?如果该方法从未返回null,则instanceof是死代码。通常,空值检查只需要1个CPU时钟,顺便说一下。 - bestsss
@bestsss:啊,我最初用的是Integer写的例子,后来改成了Object以避免包装/解包的麻烦。谢谢你指出来,我会进行更正。 - Paŭlo Ebermann
如果JIT可以内联代码(而不是某些多目标虚拟代码),并且最终结果永远不会为null,则(o instanceof String)将被省略。我试图解释一下:在性能方面,人们真正应该考虑的唯一操作是访问内存,其他操作都已经得到了很好的优化。 - bestsss

2

没有太大的开销。它几乎肯定比自己编写一个类似于getType()的解决方案更便宜。转换虽然不是免费的,但也非常便宜。

正如Bozho所指出的那样,这可能意味着设计有缺陷,但在某些情况下,它是最实用的选择,因此不应该被轻易忽略。


3
铸造虽然不是免费的,但也非常便宜。在执行 instanceof 后就变成了免费。 - bestsss

2

主要问题在于它会产生代码异味。如果使用多态性,这是更好的设计方法。性能成本可能在10到100纳秒之间,具体取决于调用的复杂性以及从该行代码调用了多少实现方法。


你是如何计算出10纳秒的开销的?还有没有其他更为常见的操作需要同样的时间? - Louis CAD
@LouisCAD 这是一个估计的平均值。注意:这取决于许多因素,所以可能会更高。 - Peter Lawrey
1
@PeterLawrey,那么你对于"模式匹配"有什么看法呢?是代码异味吗?你对访问者模式的实现有什么建议? - RamPrakash
@RamPrakash最好的模式是多态性,如果你可以改变所涉及的类来使用它。然而,如果这些类已经存在,而且你不能或不应该改变它们,或者这将涉及添加一个你不希望成为公共API的方法,instanceof可能是一种解决办法。 - Peter Lawrey

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