我正在开发一个应用程序,其中一个设计方法涉及到大量使用instanceof操作符。虽然我知道OO设计通常试图避免使用instanceof,但那是另一回事,这个问题纯粹与性能有关。我想知道是否对性能有影响?和==一样快吗?
例如,我有一个有10个子类的基类。在接受基类的单个函数中,我检查类是否是子类的实例并执行一些例程。
我想到的另一种解决方法是使用“type id”整数原语,并使用位掩码来表示子类的类别,然后对子类“type id”与表示类别的常量掩码进行位掩码比较。
instanceof是否被JVM优化得更快?我想坚持使用Java,但应用程序的性能至关重要。如果有人曾经在这条路上走过,可以提供一些建议,那就太棒了。我是不是太挑剔了,或者专注在错误的地方去优化?
InstanceOf是一个糟糕的面向对象设计的警告。
当前的jvm意味着instanceOf本身并不是一个性能问题。如果您发现自己经常使用它,特别是在核心功能方面,那么可能是时候考虑一下设计了。重构为更好的设计所带来的性能(和简单性/可维护性)收益将大大超过实际instanceOf调用所花费的实际处理器周期。
给出一个非常简单的编程示例。
if (SomeObject instanceOf Integer) {
[do something]
}
if (SomeObject instanceOf Double) {
[do something different]
}
是一个糟糕的架构,更好的选择是让SomeObject成为两个子类的父类,其中每个子类重写一个方法(doSomething),这样代码看起来就像这样:
Someobject.doSomething();
我有同样的问题,但因为我没有找到类似于我的用例的“性能指标”,我做了一些更多的示例代码。在我的硬件和Java 6和7上,instanceof和switch在1000万次迭代上的区别是
for 10 child classes - instanceof: 1200ms vs switch: 470ms
for 5 child classes - instanceof: 375ms vs switch: 204ms
因此,instanceof确实比较慢,特别是在大量的if-else-if语句上,但是在实际应用中差异可以忽略不计。
import java.util.Date;
public class InstanceOfVsEnum {
public static int c1, c2, c3, c4, c5, c6, c7, c8, c9, cA;
public static class Handler {
public enum Type { Type1, Type2, Type3, Type4, Type5, Type6, Type7, Type8, Type9, TypeA }
protected Handler(Type type) { this.type = type; }
public final Type type;
public static void addHandlerInstanceOf(Handler h) {
if( h instanceof H1) { c1++; }
else if( h instanceof H2) { c2++; }
else if( h instanceof H3) { c3++; }
else if( h instanceof H4) { c4++; }
else if( h instanceof H5) { c5++; }
else if( h instanceof H6) { c6++; }
else if( h instanceof H7) { c7++; }
else if( h instanceof H8) { c8++; }
else if( h instanceof H9) { c9++; }
else if( h instanceof HA) { cA++; }
}
public static void addHandlerSwitch(Handler h) {
switch( h.type ) {
case Type1: c1++; break;
case Type2: c2++; break;
case Type3: c3++; break;
case Type4: c4++; break;
case Type5: c5++; break;
case Type6: c6++; break;
case Type7: c7++; break;
case Type8: c8++; break;
case Type9: c9++; break;
case TypeA: cA++; break;
}
}
}
public static class H1 extends Handler { public H1() { super(Type.Type1); } }
public static class H2 extends Handler { public H2() { super(Type.Type2); } }
public static class H3 extends Handler { public H3() { super(Type.Type3); } }
public static class H4 extends Handler { public H4() { super(Type.Type4); } }
public static class H5 extends Handler { public H5() { super(Type.Type5); } }
public static class H6 extends Handler { public H6() { super(Type.Type6); } }
public static class H7 extends Handler { public H7() { super(Type.Type7); } }
public static class H8 extends Handler { public H8() { super(Type.Type8); } }
public static class H9 extends Handler { public H9() { super(Type.Type9); } }
public static class HA extends Handler { public HA() { super(Type.TypeA); } }
final static int cCycles = 10000000;
public static void main(String[] args) {
H1 h1 = new H1();
H2 h2 = new H2();
H3 h3 = new H3();
H4 h4 = new H4();
H5 h5 = new H5();
H6 h6 = new H6();
H7 h7 = new H7();
H8 h8 = new H8();
H9 h9 = new H9();
HA hA = new HA();
Date dtStart = new Date();
for( int i = 0; i < cCycles; i++ ) {
Handler.addHandlerInstanceOf(h1);
Handler.addHandlerInstanceOf(h2);
Handler.addHandlerInstanceOf(h3);
Handler.addHandlerInstanceOf(h4);
Handler.addHandlerInstanceOf(h5);
Handler.addHandlerInstanceOf(h6);
Handler.addHandlerInstanceOf(h7);
Handler.addHandlerInstanceOf(h8);
Handler.addHandlerInstanceOf(h9);
Handler.addHandlerInstanceOf(hA);
}
System.out.println("Instance of - " + (new Date().getTime() - dtStart.getTime()));
dtStart = new Date();
for( int i = 0; i < cCycles; i++ ) {
Handler.addHandlerSwitch(h1);
Handler.addHandlerSwitch(h2);
Handler.addHandlerSwitch(h3);
Handler.addHandlerSwitch(h4);
Handler.addHandlerSwitch(h5);
Handler.addHandlerSwitch(h6);
Handler.addHandlerSwitch(h7);
Handler.addHandlerSwitch(h8);
Handler.addHandlerSwitch(h9);
Handler.addHandlerSwitch(hA);
}
System.out.println("Switch of - " + (new Date().getTime() - dtStart.getTime()));
}
}