我正在开发一个应用程序,其中一个设计方法涉及到大量使用instanceof操作符。虽然我知道OO设计通常试图避免使用instanceof,但那是另一回事,这个问题纯粹与性能有关。我想知道是否对性能有影响?和==一样快吗?
例如,我有一个有10个子类的基类。在接受基类的单个函数中,我检查类是否是子类的实例并执行一些例程。
我想到的另一种解决方法是使用“type id”整数原语,并使用位掩码来表示子类的类别,然后对子类“type id”与表示类别的常量掩码进行位掩码比较。
instanceof是否被JVM优化得更快?我想坚持使用Java,但应用程序的性能至关重要。如果有人曾经在这条路上走过,可以提供一些建议,那就太棒了。我是不是太挑剔了,或者专注在错误的地方去优化?
方法
我写了一个基准程序来评估不同的实现:
实例实现(作为参考)
通过抽象类和@Override测试方法实现面向对象
使用自己的类型实现
getClass() == _.class实现
我使用jmh运行了100个预热调用、1000个测试迭代和10个分支的基准测试。因此,每个选项都测量了10,000次,在我的MacBook Pro上运行macOS 10.12.4和Java 1.8的整个基准测试需要12:18:57。该基准衡量每个选项的平均时间。要了解更多细节,请参阅我在GitHub上的实现。
为了完整起见:这个答案和我的基准有一个以前的版本。
结果
| Operation | Runtime in nanoseconds per operation | Relative to instanceof |
|------------|--------------------------------------|------------------------|
| INSTANCEOF | 39,598 ± 0,022 ns/op | 100,00 % |
| GETCLASS | 39,687 ± 0,021 ns/op | 100,22 % |
| TYPE | 46,295 ± 0,026 ns/op | 116,91 % |
| OO | 48,078 ± 0,026 ns/op | 121,42 % |
博士tl;
在Java 1.8中,instanceof是最快的方法,尽管getClass()非常接近。
方法
我写了一个基准程序来评估不同的实现:
实例实现(作为参考)
通过抽象类和@Override测试方法实现面向对象
使用自己的类型实现
getClass() == _.class实现
我使用jmh运行了100个预热调用、1000个测试迭代和10个分支的基准测试。因此,每个选项都测量了10,000次,在我的MacBook Pro上运行macOS 10.12.4和Java 1.8的整个基准测试需要12:18:57。该基准衡量每个选项的平均时间。要了解更多细节,请参阅我在GitHub上的实现。
为了完整起见:这个答案和我的基准有一个以前的版本。
结果
| Operation | Runtime in nanoseconds per operation | Relative to instanceof |
|------------|--------------------------------------|------------------------|
| INSTANCEOF | 39,598 ± 0,022 ns/op | 100,00 % |
| GETCLASS | 39,687 ± 0,021 ns/op | 100,22 % |
| TYPE | 46,295 ± 0,026 ns/op | 116,91 % |
| OO | 48,078 ± 0,026 ns/op | 121,42 % |
博士tl;
在Java 1.8中,instanceof是最快的方法,尽管getClass()非常接近。