В чем разница между ключевыми словами instanceof и in? - PullRequest
0 голосов
/ 31 октября 2018

В целях проверки принадлежности к классу ключевые слова in и instanceof ведут себя идентично. Так в чем же разница между этими двумя? Есть ли вообще разница? Существует несколько вопросов по 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 Ответ

0 голосов
/ 31 октября 2018

Основное отличие состоит в том, что instanceof является ключевым словом Java, а obj in SomeClass является эквивалентом вызова метода SomeClass.isCase(obj), как вы упомянули в своем вопросе.

Существует одно важное следствие: instanceof не может быть переопределено, и, как говорится в документации Oracle:

Оператор instanceof сравнивает объект с указанным типом. Вы можете использовать его, чтобы проверить, является ли объект экземпляром класса, экземпляром подкласса или экземпляром класса, который реализует определенный интерфейс.


Class.isCase(obj) реализован следующим образом:

<code>/**
 * 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
 * }
* * @param caseValue значение регистра * @param switchValue значение переключателя * @return true, если switchValue считается назначаемым из данного класса * @since 1.0 * / public static boolean isCase (Class caseValue, Object switchValue) { if (switchValue instanceof Class) { Класс val = (Класс) 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.

...