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

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

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

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


当前回答

如果它确实是项目中的性能问题,您应该进行测量/分析。如果是的话,我建议重新设计——如果可能的话。我很确定你不能打败平台的本机实现(用C编写)。在这种情况下,你还应该考虑多重继承。

你应该告诉更多关于这个问题,也许你可以使用一个关联存储,例如Map<Class,对象>如果你只对具体类型感兴趣。

其他回答

我也更喜欢枚举方法,但我将使用抽象基类强制子类实现getType()方法。

public abstract class Base
{
  protected enum TYPE
  {
    DERIVED_A, DERIVED_B
  }

  public abstract TYPE getType();

  class DerivedA extends Base
  {
    @Override
    public TYPE getType()
    {
      return TYPE.DERIVED_A;
    }
  }

  class DerivedB extends Base
  {
    @Override
    public TYPE getType()
    {
      return TYPE.DERIVED_B;
    }
  }
}

You're focusing on the wrong thing. The difference between instanceof and any other method for checking the same thing would probably not even be measurable. If performance is critical then Java is probably the wrong language. The major reason being that you can't control when the VM decides it wants to go collect garbage, which can take the CPU to 100% for several seconds in a large program (MagicDraw 10 was great for that). Unless you are in control of every computer this program will run on you can't guarantee which version of JVM it will be on, and many of the older ones had major speed issues. If it's a small app you may be ok with Java, but if you are constantly reading and discarding data then you will notice when the GC kicks in.

Instanceof非常快。它可以归结为用于类引用比较的字节码。在一个循环中尝试几百万个实例,自己看看。

如果它确实是项目中的性能问题,您应该进行测量/分析。如果是的话,我建议重新设计——如果可能的话。我很确定你不能打败平台的本机实现(用C编写)。在这种情况下,你还应该考虑多重继承。

你应该告诉更多关于这个问题,也许你可以使用一个关联存储,例如Map<Class,对象>如果你只对具体类型感兴趣。

很难说一个特定的JVM是如何实现实例的,但在大多数情况下,对象与结构相当,类也是如此,每个对象结构都有一个指向它是实例的类结构的指针。实际上是instanceof for

if (o instanceof java.lang.String)

可能和下面的C代码一样快

if (objectStruct->iAmInstanceOf == &java_lang_String_class)

假设JIT编译器已经就位,并且工作出色。

考虑到这只是访问一个指针,在指针指向的某个偏移量处获得一个指针,并将其与另一个指针进行比较(这基本上与测试32位数字是否相等相同),我认为操作实际上可以非常快。

但是,这并不一定是必须的,它在很大程度上取决于JVM。但是,如果这将成为代码中的瓶颈操作,我认为JVM实现相当糟糕。即使没有JIT编译器,只解释代码,也应该能够在几乎没有时间的情况下创建一个实例测试。