Оператор "instanceof" ведет себя по-разному для интерфейсов и классов
Я хотел бы узнать о следующем поведении оператора instanceof
в Java.
interface C {}
class B {}
public class A {
public static void main(String args[]) {
B obj = new B();
System.out.println(obj instanceof A); //Gives compiler error
System.out.println(obj instanceof C); //Gives false as output
}
}
Почему так? Между interface C
и class B
нет отношения, но он дает false, тогда как в случае obj instanceof A
он дает ошибку компилятора?
Ответы
Ответ 1
Поскольку Java не имеет наследования множественного класса, он абсолютно известен во время компиляции, что объект obj
типа B
не может быть подтипом A
. С другой стороны, возможно, это подтип интерфейса C
, например, в этом случае:
interface C {}
class B {}
class D extends B implements C {}
public class A {
public static void main(String args[]) {
B obj = new D();
System.out.println(obj instanceof C); //compiles and gives true as output
}
}
Поэтому, глядя только на obj instanceof C
, компилятор выражения не может заранее сказать, будет ли он истинным или ложным, но, глядя на obj instanceof A
, он знает, что это всегда ложно, поэтому бессмысленно и помогает предотвратить ошибку. Если вы все еще хотите иметь эту бессмысленную проверку в своей программе, вы можете добавить явное литье в Object
:
System.out.println(((Object)obj) instanceof A); //compiles fine
Ответ 2
Используя модификатор final
в объявлении класса ниже, гарантируется, что не может быть подкласса Test
, который может реализовать интерфейс Foobar
. В этом случае очевидно, что Test
и Foobar
несовместимы друг с другом:
public final class Test {
public static void main(String[] args) {
Test test = new Test();
System.out.println(test instanceof Foobar); // Compiler error: incompatible types
}
}
interface Foobar {
}
В противном случае, если Test
не объявлен final
, возможно, что подкласс Test
реализует интерфейс. И поэтому компилятор допустил бы оператор test instanceof Foobar
в этом случае.