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

时间:2018-10-31 19:52:29

标签: groovy types instanceof

出于验证类成员身份的目的ininstanceof关键字的行为似乎相同。那么两者之间有什么区别?根本没有区别吗?关于StackOverflow(herehere)有几个问题,其中两个关键字都是为此目的提供的解决方案,但是没有提及两者之间的区别或者何时更适合使用一个在其他。此外,官方文献中提到了the in keyword is equivalent to calling an object's isCase() method,但没有详细说明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 个答案:

答案 0 :(得分:2)

主要区别在于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()的实现,但是不能更改instanceof Java关键字的行为。如果您将Class.isCase()替代Java的instanceof关键字,则覆盖canvas可能会对您的代码造成一些损害。