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.