【问题标题】:instanceof Vs getClass( )instanceof 与 getClass( )
【发布时间】:2011-06-26 18:21:20
【问题描述】:

我发现使用 getClass()== 运算符比使用 instanceOf 运算符时性能有所提高。

Object  str = new Integer("2000");

long starttime = System.nanoTime();

if(str instanceof String) {
    System.out.println("its string");
} else {
    if (str instanceof Integer) {
        System.out.println("its integer");

    }
}

System.out.println((System.nanoTime()-starttime));

starttime = System.nanoTime();

if(str.getClass() == String.class) {
    System.out.println("its string in equals");
} else {
    if(str.getClass() == Integer.class) {
        System.out.println("its integer");
    }
}

System.out.println((System.nanoTime()-starttime));

是否有任何指导方针,使用getClass()instanceOf 中的哪一个?

给定一个场景:我知道要匹配的确切类,即StringInteger(这些是最终类)等。

使用instanceOf 操作符是不好的做法吗?

【问题讨论】:

  • 您的计时方法导致人为延迟并产生不正确的计时结果。交换您进行检查的顺序,您会看到您所做的第一次检查(== 或 instanceof)总是会更长。我猜它是 println()s。你永远不应该在你的时间块中包含这些东西。
  • 只有一条评论,为了比较性能,使用多个循环迭代(例如10000)以提高准确性。一次调用不是一个好的衡量标准。
  • 差别有多大?

标签: java class instanceof


【解决方案1】:

instanceofgetClass() == ... 的性能不同的原因是他们在做不同的事情。

  • instanceof 测试左侧 (LHS) 上的对象引用是右侧 (RHS) 类型的实例还是某个子类型

  • getClass() == ... 测试类型是否相同。

因此,建议忽略性能问题并使用能够为您提供所需答案的替代方案。

使用instanceOf 操作符是不好的做法吗?

不一定。过度使用instanceOfgetClass() 可能是“设计气味”。如果您不小心,您最终会得到一个设计,其中添加新的子类会导致大量代码返工。在大多数情况下,首选方法是使用多态性。

但是,在某些情况下,这些不是“设计气味”。例如,在equals(Object) 中,您需要测试参数的实际类型,如果不匹配则返回false。最好使用getClass() 来完成。


应谨慎使用“最佳实践”、“不良实践”、“设计味道”、“反模式”等术语,并应谨慎对待。他们鼓励非黑即白的思考。最好根据上下文做出判断,而不是仅仅基于教条;例如有人说的是“最佳实践”。我建议大家阅读No Best Practices,如果他们还没有这样做的话。

【讨论】:

    【解决方案2】:

    你想匹配一个类完全,例如只匹配FileInputStream 而不是FileInputStream 的任何子类?如果是这样,请使用getClass()==。我通常会在equals 中执行此操作,因此 X 的实例不被视为等于 X 的子类的实例 - 否则您可能会遇到棘手的对称问题。另一方面,这对于比较两个对象是否属于 相同 类而不是一个特定类更有用。

    否则,请使用instanceof。请注意,对于getClass(),您需要确保以非空引用开头,否则您将获得NullPointerException,而如果第一个操作数为空,instanceof 将只返回false

    我个人会说instanceof 更惯用 - 但在大多数情况下,广泛使用它们中的任何一个 都是一种设计味道。

    【讨论】:

      【解决方案3】:

      我知道这个问题已经有一段时间了,但我昨天学到了一个替代方法

      我们都知道你可以做到:

      if(o instanceof String) {   // etc
      

      但是,如果您不确切知道它需要是什么类型的类怎么办? 你一般不能这样做:

      if(o instanceof <Class variable>.getClass()) {   
      

      因为它给出了编译错误。
      相反,这是一个替代方案 - isAssignableFrom()

      例如:

      public static boolean isASubClass(Class classTypeWeWant, Object objectWeHave) {
      
          return classTypeWeWant.isAssignableFrom(objectWeHave.getClass())
      }
      

      【讨论】:

      • 不要使用isAssignableFrom。使用反射编写o instanceof String 的正确方法是String.getClass().isInstance(o)。 javadoc 甚至这样说:此方法是 Java 语言 instanceof 运算符的动态等效方法。
      【解决方案4】:

      getClass() 的限制是对象只能与同一类、同一运行时类型的其他对象相等,如下代码的输出所示:

      class ParentClass{
      }
      public class SubClass extends ParentClass{
          public static void main(String []args){
              ParentClass parentClassInstance = new ParentClass();
              SubClass subClassInstance = new SubClass();
              if(subClassInstance instanceof ParentClass){
                  System.out.println("SubClass extends ParentClass. subClassInstance is instanceof ParentClass");
              }
              if(subClassInstance.getClass() != parentClassInstance.getClass()){
                  System.out.println("Different getClass() return results with subClassInstance and parentClassInstance ");
              }
          }
      }
      

      输出:

      子类扩展父类。 subClassInstance 是 ParentClass 的实例。

      不同的 getClass() 返回结果与 subClassInstance 和 parentClassInstance。

      【讨论】:

        猜你喜欢
        • 2015-09-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-24
        相关资源
        最近更新 更多