The 'instanceof' operator behaves differently for interfaces and classes
Asked Answered
S

3

91

I would like to know regarding following behavior of instanceof operator in 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
    }
}

Why is it so? There is no relation between interface C and class B, but it gives false whereas in case of obj instanceof A it gives compiler error?

Skepful answered 14/7, 2015 at 5:39 Comment(4)
Note: if you change it to Object obj = new B(), it compiles.Cartelize
What does the compiler Error tell you?Selestina
If class B is final then obj instanceof C will not compile either, because if B can have no subtypes, then it is guaranteed to be unrelated to C.Sosthina
https://mcmap.net/q/242533/-instanceof-with-an-interface-duplicate As said in the above answer, B is not a subclass of A. so B's subclasses can never be an instance of A (never ever). so, compile time error occurs. But that's not the case with interface C. any subclass of B can implement C, there is no restriction to do so. So the code compiles.Sarazen
G
131

Because Java has no multiple class inheritance it's absolutely known during the compilation that obj object of type B cannot be subtype of A. On the other hand it possibly can be subtype of interface C, for example in this case:

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  
    }
}

So looking only at obj instanceof C expression compiler cannot tell in advance whether it will be true or false, but looking at obj instanceof A it knows that this is always false, thus meaningless and helps you to prevent an error. If you still want to have this meaningless check in your program, you can add an explicit casting to the Object:

System.out.println(((Object)obj) instanceof A);      //compiles fine
Gigantism answered 14/7, 2015 at 5:49 Comment(4)
The other flavor of a meaningless check is to use A.class.isAssignableFrom(obj.getClass())Ywis
I am bit confused with your explanation you said Java has no multiple class inheritance yes I agree but how it is applied in this case because neither B or A extends anyting so why multiple inheritence here.It would be helpful if you can explain?Vaas
@Vaas Late answer: If Java allowed a class to inherit from multiple other classes, then one could do "class D extends A, B" or some such, and then "B obj = new D()", and make the "obj instanceof A" in the original question compile (whereas it currently does not)--in fact it had better compile, because it would be expected to evaluate to true. But if it's simply not allowed for anything to be both B and A, then the expression "obj instanceof A" where obj is defined as type B can be reasonably considered to be nonsensical.Standush
" If you still want to have this meaningless check" - it does not need to be meaningless, as if this classes are from other library/framework then there is chance that you will be using different version at runtime where B extends A. In my life I actually needed to do such weird checks and casts like (A)(Object)b as in runtime it was actually possible to be true.Zurek
L
2

By using the final modifier in the class declaration below, it is guaranteed that there couldn't be a subclass of Test, which may implement the interface Foobar. In this case, it is obvious that Test and Foobar are not compatible with each other:

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 {
}

Otherwise, if Test is not declared final, it might be possible that a subclass of Test implements the interface. And that's why the compiler would allow the statement test instanceof Foobar in this case.

Lathi answered 18/11, 2017 at 16:26 Comment(0)
B
1

I'm not sure about which Java version you are concerning to, but sealed interfaces/classes (>=17) are a way of detecting this in compiling time. In this example is explicit D the only class could implement C, and A or B not:

sealed interface C permits D {}

class B {}

final class D implements C {}

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 ANOTHER compiler error
    }
}

See: https://docs.oracle.com/en/java/javase/17/language/sealed-classes-and-interfaces.html

Butterflies answered 16/6 at 18:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.