我正在开发一个应用程序,其中一个设计方法涉及到大量使用instanceof操作符。虽然我知道OO设计通常试图避免使用instanceof,但那是另一回事,这个问题纯粹与性能有关。我想知道是否对性能有影响?和==一样快吗?

例如,我有一个有10个子类的基类。在接受基类的单个函数中,我检查类是否是子类的实例并执行一些例程。

我想到的另一种解决方法是使用“type id”整数原语,并使用位掩码来表示子类的类别,然后对子类“type id”与表示类别的常量掩码进行位掩码比较。

instanceof是否被JVM优化得更快?我想坚持使用Java,但应用程序的性能至关重要。如果有人曾经在这条路上走过,可以提供一些建议,那就太棒了。我是不是太挑剔了,或者专注在错误的地方去优化?


当前回答

我认为在本页提交一个反例来反驳“instanceof”的普遍共识是值得的。我发现我在一个内循环中有一些代码(在一些历史性的优化尝试中)

if (!(seq instanceof SingleItem)) {
  seq = seq.head();
}

在SingleItem上调用head()返回的值不变。将代码替换为

seq = seq.head();

让我从269毫秒加速到169ms,尽管事实上在循环中发生了一些相当繁重的事情,比如字符串到双精度转换。当然,加速可能更多是由于消除了条件分支,而不是消除了操作符本身的实例;但我觉得值得一提。

其他回答

现代JVM/JIT编译器已经消除了大多数传统的“慢”操作对性能的影响,包括instanceof、异常处理、反射等。

正如Donald Knuth所写的,“我们应该忘记小的效率,大约97%的时候:过早的优化是万恶之源。”instanceof的性能可能不是问题,所以在确定问题所在之前,不要浪费时间想出奇异的解决方案。

Instanceof非常高效,因此您的性能不太可能受到影响。 然而,使用大量的instanceof暗示了一个设计问题。

如果您可以使用xClass == String.class,这将更快。注意:final类不需要instanceof。

我只是做了一个简单的测试,看看instanceOf的性能如何与对一个只有一个字母的字符串对象的简单s.equals()调用进行比较。

在10.000.000循环中,instanceOf给了我63-96ms,而字符串equals给了我106-230ms

我使用java jvm 6。

所以在我的简单测试中,做一个instanceOf而不是一个字符串比较更快。

使用Integer的.equals()而不是string的给了我相同的结果,只有当我使用== I比instanceOf快20ms(在10.000.000循环中)

我认为在本页提交一个反例来反驳“instanceof”的普遍共识是值得的。我发现我在一个内循环中有一些代码(在一些历史性的优化尝试中)

if (!(seq instanceof SingleItem)) {
  seq = seq.head();
}

在SingleItem上调用head()返回的值不变。将代码替换为

seq = seq.head();

让我从269毫秒加速到169ms,尽管事实上在循环中发生了一些相当繁重的事情,比如字符串到双精度转换。当然,加速可能更多是由于消除了条件分支,而不是消除了操作符本身的实例;但我觉得值得一提。

一般来说,在这种情况下(instanceof检查这个基类的子类)不支持使用“instanceof”操作符的原因是,您应该做的是将操作移动到一个方法中,并为适当的子类重写它。例如,如果你有:

if (o instanceof Class1)
   doThis();
else if (o instanceof Class2)
   doThat();
//...

你可以用

o.doEverything();

然后在Class1中调用“doEverything()”的实现,在Class2中调用“doThat()”,以此类推。