web-dev-qa-db-fra.com

L'opérateur 'instanceof' se comporte différemment pour les interfaces et les classes

Je voudrais connaître le comportement suivant de l'opérateur instanceof en 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
    }
}

Pourquoi en est-il ainsi? Il n'y a pas de relation entre interface C et class B, mais ça donne faux alors qu'en cas de obj instanceof A cela donne une erreur de compilation?

88
Ajay Sharma

Parce que Java n'a pas d'héritage de classes multiples, il est absolument connu lors de la compilation que obj objet de type B ne peut pas être un sous-type de A. On d'autre part cela peut éventuellement être un sous-type d'interface C, par exemple dans ce cas:

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

Donc, en regardant uniquement obj instanceof C le compilateur d'expressions ne peut pas dire à l'avance si ce sera vrai ou faux, mais en regardant obj instanceof A il sait que c'est toujours faux, donc vide de sens et vous aide à éviter une erreur. Si vous voulez toujours avoir cette vérification vide de sens dans votre programme, vous pouvez ajouter un casting explicite à Object:

System.out.println(((Object)obj) instanceof A);      //compiles fine
127
Tagir Valeev

En utilisant le modificateur final dans la déclaration de classe ci-dessous, il est garanti qu'il ne peut pas y avoir de sous-classe de Test, qui peut implémenter l'interface Foobar. Dans ce cas, il est évident que Test et Foobar ne sont pas compatibles entre eux:

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

Sinon, si Test n'est pas déclaré final, il se peut qu'une sous-classe de Test implémente l'interface. Et c'est pourquoi le compilateur autoriserait l'instruction test instanceof Foobar dans ce cas.

1
Nurettin Armutcu