Перейти к основному содержимому

Оператор экземпляра Java

· 4 мин. чтения

1. Введение

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

2. Что такое экземпляр оператора?

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

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

Основной синтаксис оператора instanceof :

(object) instanceof (type)

Давайте посмотрим на базовый пример оператора instanceof . Во-первых, давайте создадим класс Round :

public class Round {
// implementation details
}

Далее создадим класс Ring , расширяющий Round :

public class Ring extends Round {
// implementation details
}

Мы можем использовать instanceof , чтобы проверить, относится ли экземпляр Ring к типу Round :

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

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

Оператор instanceof работает по принципу отношения is-a . Концепция отношения 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 и дженерики

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

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

public static <T> void sort(List<T> collection) {
if (collection instanceof List<String>) {
// sort strings differently
}

// omitted
}

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

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

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

Овеществленные типы в Java следующие:

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

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

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

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

if (collection instanceof List<?>) {
// do something
}

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

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