“instanceof”和“in”关键字有什么区别?

3
为了验证类成员身份ininstanceof 关键字似乎表现相同。那么两者之间有什么区别呢?它们是否真的有区别?在 StackOverflow 上有几个问题(这里这里)给出了这两个关键字作为解决方案,但没有提到它们之间的区别或何时更适合使用其中之一。此外,官方文档提到 in 关键字等同于调用对象的 isCase() 方法, 但没有详细说明 instanceof 关键字的作用。

这两个关键字在类继承和接口实现方面似乎表现相同:

class MyMap extends LinkedHashMap { }

def foo = new LinkedHashMap()
def bar = new MyMap()

println("LinkedHashMap instance is 'in' LinkedHashMap: ${foo in LinkedHashMap}")
println("LinkedHashMap instance is 'instanceof' LinkedHashMap: ${foo instanceof LinkedHashMap}")
println("LinkedHashMap instance is 'in' Map: ${foo in Map}")
println("LinkedHashMap instance is 'instanceof' Map: ${foo instanceof Map}")
println("MyMap instance is 'in' LinkedHashMap: ${bar in LinkedHashMap}")
println("MyMap instance is 'instanceof' LinkedHashMap: ${bar instanceof LinkedHashMap}")
println("MyMap instance is 'in' Map: ${bar in Map}")
println("MyMap instance is 'instanceof' Map: ${bar instanceof Map}")

输出:

LinkedHashMap instance is 'in' LinkedHashMap: true
LinkedHashMap instance is 'instanceof' LinkedHashMap: true
LinkedHashMap instance is 'in' Map: true
LinkedHashMap instance is 'instanceof' Map: true
MyMap instance is 'in' LinkedHashMap: true
MyMap instance is 'instanceof' LinkedHashMap: true
MyMap instance is 'in' Map: true
MyMap instance is 'instanceof' Map: true
1个回答

6
主要区别在于instanceof是Java关键字,而obj in SomeClass等同于您在问题中提到的SomeClass.isCase(obj)方法调用。
有一个主要影响:无法覆盖instanceof,正如Oracle文档所述:
instanceof运算符将对象与指定类型进行比较。您可以使用它来测试对象是否是类的实例、子类的实例或实现特定接口的类的实例。”
源自:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html Class.isCase(obj)的实现如下:
/**
 * Special 'Case' implementation for Class, which allows testing
 * for a certain class in a switch statement.
 * For example:
 * <pre>switch( obj ) {
 *   case List :
 *     // obj is a list
 *     break;
 *   case Set :
 *     // etc
 * }</pre>
 *
 * @param caseValue   the case value
 * @param switchValue the switch value
 * @return true if the switchValue is deemed to be assignable from the given class
 * @since 1.0
 */
public static boolean isCase(Class caseValue, Object switchValue) {
    if (switchValue instanceof Class) {
        Class val = (Class) switchValue;
        return caseValue.isAssignableFrom(val);
    }
    return caseValue.isInstance(switchValue);
}

来源: org/codehaus/groovy/runtime/DefaultGroovyMethods.java#L1121

从源代码中可以看出,基于 Groovy 的 obj in SomeClass 并不是 instanceof 的别名,因为它做了更多的事情。然而,有一件重要的事情值得一提 - 你可以重写 isCase() 的实现,但你不能改变 Java 关键字 instanceof 的行为。如果你将其作为 Java instanceof 关键字的替代方案并覆盖 Class.isCase(),可能会对你的代码造成一些损害。


哇,非常详细的回答并附有来源。谢谢!我还想知道是否存在任何情况下 someObject instanceof SomeClasssomeObject in SomeClass 的行为会有所不同(除了覆盖 isCase())。根据给定的信息,似乎在所有实际目的下,这两者的行为都是相同的,即使它们不是严格等价的。 - jayhendren
发现一个不同之处:Object in Class -> false. Object instanceof Class -> true. - jayhendren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接