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 .