Оператор instanceof Java

1. Введение

В этом кратком руководстве мы узнаем об операторе instanceof в Java.

2. Что такое оператор instanceof ?

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

Перед приведением неизвестного объекта всегда следует использовать проверку instanceof . Это помогает избежать исключения ClassCastException во время выполнения.

В InstanceOf базовый синтаксис оператора заключается в следующем :

(object) instanceof (type)

Давайте посмотрим на базовый пример оператора instanceof . Сначала создадим класс Round :

public class Round { // implementation details }

Затем давайте создадим класс Ring, который расширяет Round :

public class Ring extends Round { // implementation details }

Мы можем использовать InstanceOf , чтобы проверить , если экземпляр кольца имеет круглого типа:

@Test public void givenWhenInstanceIsCorrect_thenReturnTrue() { Ring ring = new Ring(); Assert.assertTrue(ring instanceof Round); }

3. Как работает instanceof Operator?

Оператор instanceof работает по принципу отношения is-a . Концепция отношения «есть-есть» основана на наследовании классов или реализации интерфейса.

Чтобы продемонстрировать это, давайте создадим интерфейс Shape :

public interface Shape { // implementation details }

Давайте также создадим класс Circle, который реализует интерфейс Shape, а также расширяет класс Round :

public class Circle extends Round implements Shape { // implementation details }

Результат instanceof будет истинным, если объект является экземпляром типа:

@Test public void givenWhenObjectIsInstanceOfType_thenReturnTrue() { Circle circle = new Circle(); Assert.assertTrue(circle instanceof Circle); }

Это также будет верно, если объект является экземпляром подкласса типа:

@Test public void giveWhenInstanceIsOfSubtype_thenReturnTrue() { Circle circle = new Circle(); Assert.assertTrue(circle instanceof Round); }

Если тип является интерфейсом, он вернет true, если объект реализует интерфейс:

@Test public void givenWhenTypeIsInterface_thenReturnTrue() { Circle circle = new Circle(); Assert.assertTrue(circle instanceof Shape); }

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

Давайте создадим новый класс Triangle, который реализует Shape, но не имеет отношения к Circle :

public class Triangle implements Shape { // implementation details }

Теперь, если мы используем instanceof, чтобы проверить, является ли Circle экземпляром Triangle :

@Test public void givenWhenComparingClassInDiffHierarchy_thenCompilationError() { Circle circle = new Circle(); Assert.assertFalse(circle instanceof Triangle); }

Мы получим ошибку компиляции, потому что нет связи между классами Circle и Triangle :

java.lang.Error: Unresolved compilation problem: Incompatible conditional operand types Circle and Triangle

4. Использование instanceof с типом объекта

В Java каждый класс неявно наследуется от класса Object . Следовательно, использование оператора instanceof с типом Object всегда будет иметь значение true :

@Test public void givenWhenTypeIsOfObjectType_thenReturnTrue() { Thread thread = new Thread(); Assert.assertTrue(thread instanceof Object); }

5. Использование оператора instanceof, когда объект имеет значение NULL

Если мы используем оператор instanceof для любого объекта, имеющего значение null , он возвращает false . Кроме того, при использовании оператора instanceof проверка на null не требуется .

@Test public void givenWhenInstanceValueIsNull_thenReturnFalse() { Circle circle = null; Assert.assertFalse(circle instanceof Round); }

6. instanceof и Generics

Экземплярные тесты и приведение типов зависят от проверки информации о типе во время выполнения. Следовательно, мы не можем использовать instanceof вместе со стертыми универсальными типами .

Например, если мы попытаемся скомпилировать следующий фрагмент:

public static  void sort(List collection) { if (collection instanceof List) { // sort strings differently } // omitted }

Тогда мы получаем эту ошибку компиляции:

error: illegal generic type for instanceof if (collection instanceof List) { ^

Технически говоря, нам разрешено использовать instanceof только вместе с reifiedтипы в Java. Тип реифицируется, если информация о его типе присутствует во время выполнения.

Реифицированные типы в Java следующие:

  • Примитивные типы, такие как int
  • Неуниверсальные классы и интерфейсы, такие как String или Random
  • Универсальные типы, в которых все типы являются неограниченными подстановочными знаками, такими как Set или Map
  • Необработанные типы, такие как List или HashMap
  • Массивы других реализуемых типов, таких как String [], List [] или Map []

Поскольку параметры универсального типа не реифицируются, мы также не можем их использовать:

public static  boolean isOfType(Object input) { return input instanceof T; // won't compile }

Однако можно протестировать что-то вроде List :

if (collection instanceof List) { // do something }

7. Заключение

В этом руководстве мы узнали об операторе instanceof и о том, как его использовать. Полные образцы кода доступны на GitHub.