下面哪个比较好?

a instanceof B

or

B.class.isAssignableFrom(a.getClass())

我所知道的唯一区别是,当'a'为空时,第一个返回false,而第二个抛出异常。除此之外,它们总是给出相同的结果吗?


当前回答

还有另一个区别:

不管X是什么,null instanceof X都是假的

null.getClass().isAssignableFrom(X)将抛出NullPointerException

其他回答

这完全取决于代码中此时可用的内容。我不建议使用isAssignableFrom如果你正在使用一个实际的对象-有一个更好的选择。下面是一份根据你所拥有的产品进行排名的推荐列表:

如果你有一个对象a,并且你在编译时知道类型B: a instanceof实例 如果你有一个对象a,你不知道类型B,但你有一个对象B: .isInstance b.getClass () () 如果你有一个对象a,在编译时没有类型或实例化对象,但你有一个类对象class <?> someBClass: someBClass.isInstance (a) 如果你没有实例化对象,但是你有两个Class<?>对象: someBClass.isAssignableFrom (someAClass)。

假设你从列表的顶部开始,然后往下做,每一种方法都是实现目标的最简单的方法,根据我自己的研究,我相信你也会得到最好的表现。

用一些例子来证明它怎么样?

@Test
public void isInstanceOf() {
    Exception anEx1 = new Exception("ex");
    Exception anEx2 = new RuntimeException("ex");
    RuntimeException anEx3 = new RuntimeException("ex");

    //Base case, handles inheritance
    Assert.assertTrue(anEx1 instanceof Exception);
    Assert.assertTrue(anEx2 instanceof Exception);
    Assert.assertTrue(anEx3 instanceof Exception);

    //Other cases
    Assert.assertFalse(anEx1 instanceof RuntimeException);
    Assert.assertTrue(anEx2 instanceof RuntimeException);
    Assert.assertTrue(anEx3 instanceof RuntimeException);
}

@Test
public void isAssignableFrom() {
    Exception anEx1 = new Exception("ex");
    Exception anEx2 = new RuntimeException("ex");
    RuntimeException anEx3 = new RuntimeException("ex");

    //Correct usage = The base class goes first
    Assert.assertTrue(Exception.class.isAssignableFrom(anEx1.getClass()));
    Assert.assertTrue(Exception.class.isAssignableFrom(anEx2.getClass()));
    Assert.assertTrue(Exception.class.isAssignableFrom(anEx3.getClass()));

    //Incorrect usage = Method parameter is used in the wrong order
    Assert.assertTrue(anEx1.getClass().isAssignableFrom(Exception.class));
    Assert.assertFalse(anEx2.getClass().isAssignableFrom(Exception.class));
    Assert.assertFalse(anEx3.getClass().isAssignableFrom(Exception.class));
}

还有一个不同之处。如果要测试的类型(Class)是动态的,例如,作为方法参数传递,那么instanceof将不会为你切割它。

boolean test(Class clazz) {
   return (this instanceof clazz); // clazz cannot be resolved to a type.
}

但是你可以:

boolean test(Class clazz) {
   return (clazz.isAssignableFrom(this.getClass())); // okidoki
}

哎呀,这个答案已经讲过了。也许这个例子对某人有帮助。

isAssignableFrom(A, B) =

if (A == B) return true
else if (B == java.lang.Object) return false
else return isAssignableFrom(A, getSuperClass(B))

The pseudo code above is a definition of, if references of type/class A is assignable from references of type/class B. It is a recursive definition. To some it may be helpful, for others it may be confusing. I add it in case somebody should find it useful. This is just an attempt to capture my understanding, it is not the official definition. It is used in a certain Java VM implementation and works for many example programs, so while I cannot guarentee that it captures all aspects of isAssignableFrom, it is not completely off.

我们在团队中做的一些测试表明,A.class. isassignablefrom (B. getclass())比B instanceof a工作得更快,如果你需要对大量元素进行检查,这是非常有用的。