10

If I try to use instanceof operator with wrong class I'm getting a compile error (" Animal can not be converted to String") but with an interface I'm not getting compile time error.

For eg: In line 10 I'm getting a compile error because Animal is not a subclass of String. But in line 14 I'm not getting a compile error even though Animal does not implement List interface.

class Animal {

}

public class InstanceOf {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
         Animal a = new Animal();
        if (a instanceof String ){  //line 10
            System.out.println("True");
        }

         if (a instanceof List ){ //line 14
            System.out.println("True");
        }
    }

}
nantitv
  • 3,539
  • 4
  • 38
  • 61

2 Answers2

19

a can never be an instanceof String, hence the compilation error.

a can be an instance of List if some sub-class of Animal would implement the List interface and you would assign an instance of such sub-class to a. Therefore the compiler allows it.

From the JLS :

If a cast (§15.16) of the RelationalExpression to the ReferenceType would be rejected as a compile-time error, then the instanceof relational expression likewise produces a compile-time error. In such a situation, the result of the instanceof expression could never be true.

Eran
  • 387,369
  • 54
  • 702
  • 768
  • 1
    Is java not allowed multiple inheritance is the root cause? At the same time any subclass can implement an Interface whenever it wants? – nantitv Apr 10 '16 at 11:46
  • 3
    @nantitv Yes. Since Animal is not a sub-class of String, any sub-class of Animal cannot be a sub-class of String. Though in your specific snippet, it wouldn't make a difference even if multiple inheritance was allowed, since String is final and cannot be sub-classed. – Eran Apr 10 '16 at 11:50
  • Thanks . String I just took it for an example. – nantitv Apr 10 '16 at 11:51
  • @nantitv if you tell the compiler that there will be no subclasses of `Animal`, it will in fact be able to infer that `instanceof` is pointless: simply replace `class Animal{}` by `final class Animal{}`. – CompuChip Apr 10 '16 at 19:42
2

Just an experiment I did from this question.

class Animal {}
interface AnimalA {}
class AnimalB{} 

class AnimalC extends Animal,AnimalB {} //not possible
class AnimalD extends Animal implements AnimalA{} //possible   

public class InstanceOfTest {

    public static void main(String[] args) {
        Animal a = new Animal();
        if(a instanceof AnimalA) { //no compile time error
            System.out.println("interface test");
        }
        if(a instanceof AnimalB) { //compile time error
            System.out.println("interface test");
        }
        if(a instanceof List) { //compile time error
            System.out.println("interface test");
        }
        if(a instanceof ArrayList) { //compile time error
            System.out.println("interface test");
        }
    }
}

So as @Eran said, as Animal is not a sub-class of AnimalB non of its sub-class can become and instance of AnimalB. But on the other any of its sub-class can implement interface List.