Использование instanceof

Иногда может оказаться желательным знать тип объекта во время выполнения программы. Например, вы можете иметь один поток выполнения, который генерирует объекты различных типов, и другой поток, который их использует. В этой ситуации для обрабатывающего потока может быть удобно знать тип каждого объекта, который он получает. Другая ситуация, когда знание типа объекта во время выполнения важно — это когда используется приведение типа. В Java неправильное приведение типа вызывает ошибку времени выполнения. Множество неверных приведений типа могут быть перехвачены на этапе компиляции. Однако приведение типов в пределах иерархии классов может стать причиной ошибок приведения, которые обнаруживаются только во время выполнения. Например, суперкласс по имени А может порождать два подкласса — В и С. Таким образом, приведение объекта типа В к типу А, или приведение С к А допустимо, но приведение объекта типа В к типу С (и наоборот) — некорректно. Поскольку объект типа А может ссылаться на объекты и типа В, и типа С, как вы можете узнать во время выполнения, к какому именно типу обращается ссылка перед тем, как осуществить приведение к типу С? Это может быть объект типа А, В или С. Если это объект типа В, то будет возбуждено исключение времени выполнения. Для получения ответа на этот вопрос Java предлагает операцию времени выполнения instanceof. Общая форма операции instanceof такова:

object instanceof type

Здесь object — ссылка на экземпляр класса, a type — тип класса. Если object относится к указанному типу или может быть приведен к нему, то операция instanceof дает в результате true. В противном случае результатом будет false. То есть instanceof — это средство, с помощью которого программа может получить информацию об объекте во время выполнения.

В следующей программе демонстрируется применение instanceof.

// Демонстрация использования операции instanceof.
class А {
int i, j ;
}
class В {
int i, j;
}
class С extends A {
int k;
}
class D extends A {
int k;
}
class Instanceof {
public static void main(String args[]) {
A a = new A();
В b = new В () ;
С с = new С();
D d = new D () ;
if(a instanceof A)
System.out.println ("а есть экземпляр A");
if(b instanceof B)
System.out.println ("b есть экземпляр В");
if(с instanceof С)
System.out.println ("с есть экземпляр С");
if(с instanceof А)
System.out.println("с может быть приведен к А");
if (a instanceof С)
System.out.println("а может быть приведен к С");
System.out.println();
// сравнение типов с порожденными типами A ob;
ob = d; // Ссылка на d
System.out.println ("ob теперь ссылается на d") ;
if(ob instanceof D)
System.out.println("ob есть экземпляр D");
System.out.println();
ob = с; // ссылка на с
System.out.println("ob теперь ссылается на с");
if (ob instanceof D)
System.out.println ("ob может быть приведен к D");
else
System.out.println("ob не может быть приведен к D");
if(ob instanceof A)
System.out.println("ob может быть приведен к А");
System.out.println();
// все объекты могут быть приведены к Object
if (a instanceof Object)
System.out.println("а может быть приведен к Object");
if (b instanceof Object)
System.out.println("b может быть приведен к Object");
if (с instanceof Object)
System.out.println("с может быть приведен к Object");
if(d instanceof Object)
System.out.println ("d может быть приведен к Object");
}
}

Результат работы этой программы:

а есть экземпляр А
b есть экземпляр В
с есть экземпляр С
с может быть приведен к А
ob теперь ссылается на d
ob есть экземпляр D
ob теперь ссылается на с
ob не может быть приведен к D
ob может быть приведено к А
а может быть приведен к Object
b может быть приведен к Object
с может быть приведен к Object
d может быть приведен к Object

Большинство программ не нуждаются в операции instanceof, поскольку обычно вам известны типы объектов, с которыми работаете. Однако она может оказаться очень полезной, когда вы разрабатываете обобщенные процедуры, имеющие дело с объектами из сложной иерархии классов.