instanceof与getClass()


114

我看到使用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操作员的做法不好吗?



2
您的计时方法导致人为延迟并产生不正确的计时结果。交换您执行检查的顺序,您会看到第一次检查(==或instanceof)将总是更长。我猜这是println()。您绝对不应在计时块中包含这些内容。
kurtzmarc 2012年

仅相差一句话,为了比较性能,请使用多个循环迭代(例如10000)以提高准确性。单个调用不是一个好方法。
martins.tuga 2014年

Answers:


139

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

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

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

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

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

不必要。过度使用instanceOfgetClass() 可能是 “设计异味”。如果您不小心,最终会遇到这样的设计:添加新的子类会导致大量的代码重做。在大多数情况下,首选方法是使用多态性。

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


应当谨慎使用“最佳实践”,“不良实践”,“设计气味”,“反模式”等术语,并应予以怀疑。他们鼓励黑白思维。最好是根据上下文做出判断,而不是纯粹基于教条。例如某人说的是“最佳实践”。


@StephenC正如您所说的,可以code smell使用其中一种。这意味着,不良的设计(非多态)代码会导致您使用其中任何一种。我可以以此方式推断它们的用法吗?
2014年

@overexchange-1)我说的是“过度使用”而不是“使用”。2)除此之外,我不明白您的要求。“推断使用情况...”是什么意思????代码要么使用这些东西,要么不使用。
2014年

我推断,instanceof&的使用是getClass()由于代码的现有不良设计(非多态性)而引起的。我对么?
2014年

5
@overexchange-您不能有效地推断对instanceof(例如)的所有使用都是不良设计。在某些情况下,这可能是最佳解决方案。相同getClass()。我将重复我所说的“过度使用”而不是“使用”。每个案件都需要根据其案情进行判断……而不是盲目地运用一些毫无根据的教条规则。
2014年

43

您是否要完全匹配一个类,例如,仅匹配FileInputStream而不是的任何子类FileInputStream?如果是这样,请使用getClass()==。我通常会在中执行此操作,以equals使X的实例不等于X的子类的实例-否则您将陷入棘手的对称性问题。另一方面,对于比较两个对象属于同一类而不是一个特定类而言,这通常更有用。

否则,请使用instanceof。请注意,使用时,getClass()您需要确保您具有一个非null引用开头,否则将获得NullPointerException,而如果第一个操作数为null ,instanceof则将仅返回false

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


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())
}

8
不要使用isAssignableFromo instanceof String使用反射写的正确方法是String.getClass().isInstance(o)。Javadoc甚至这样说:该方法与Java语言instanceof运算符是动态等效的。
安德烈亚斯(Andreas)

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 ");
        }
    }
}

输出:

子类扩展了ParentClass。subClassInstance是ParentClass的instance。

不同的getClass()返回结果分别带有subClassInstance和parentClassInstance。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.