130

我看到使用getClass()and==运算符而不是运算符时性能有所提高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操作员是不好的做法吗?

4

4 回答 4

160

instanceof和的表现getClass() == ...不同的原因是他们在做不同的事情。

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

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

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

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

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

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


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

于 2011-02-14T07:44:15.207 回答
48

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

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

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

于 2011-02-14T07:43:05.480 回答
18

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

我们都知道你可以做到:

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())
}
于 2012-09-26T20:55:01.983 回答
3

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。

于 2016-05-17T17:16:16.603 回答