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

88

Je voudrais connaître le comportement suivant de l' instanceofopérateur 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 Cet class B, mais cela donne false alors que dans le cas, obj instanceof Acela donne une erreur de compilation?

Ajay Sharma
la source
12
Remarque: si vous le changez en Object obj = new B(), il se compile.
user253751
1
Que vous dit l'erreur du compilateur?
karfau
Si class Best finalalors obj instanceof Cne compilera pas non plus, car si Bne peut avoir aucun sous-type, alors il est garanti qu'il n'est pas lié à C.
jaco0646

Réponses:

127

Parce que Java n'a pas d'héritage de classes multiples, il est absolument connu lors de la compilation que l' objobjet de type Bne peut pas être un sous-type A. Par contre il peut éventuellement s'agir d'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, regarder uniquement le obj instanceof Ccompilateur d'expression ne peut pas dire à l'avance s'il sera vrai ou faux, mais le regarder obj instanceof Asait que c'est toujours faux, donc dénué de sens et vous aide à éviter une erreur. Si vous souhaitez toujours avoir cette vérification sans signification dans votre programme, vous pouvez ajouter un casting explicite au Object:

System.out.println(((Object)obj) instanceof A);      //compiles fine
Tagir Valeev
la source
1
L'autre saveur d'un chèque sans signification est d'utiliserA.class.isAssignableFrom(obj.getClass())
David Ehrmann
Je suis un peu confus avec votre explication vous avez dit Java has no multiple class inheritanceoui je suis d'accord mais comment cela s'applique dans ce cas parce que ni B ni A ne s'étendent, alors pourquoi l'héritage multiple ici. Ce serait utile si vous pouvez expliquer?
codegasmer
@codegasmer Réponse tardive: Si Java permettait à une classe d'hériter de plusieurs autres classes, alors on pourrait faire "class D extend A, B" ou quelque chose de ce genre, puis "B obj = new D ()", et créer le "obj instanceof A "dans la question d'origine compile (alors que ce n'est pas le cas actuellement) - en fait, il vaut mieux compiler, car on s'attend à ce qu'il soit évalué à vrai. Mais s'il n'est tout simplement pas permis que quelque chose soit à la fois B et A, alors l'expression "obj instanceof A" où obj est défini comme type B peut être raisonnablement considérée comme absurde.
mjwach
"Si vous voulez toujours avoir cette vérification sans signification" - cela n'a pas besoin d'être dénué de sens, comme si ces classes provenaient d'une autre bibliothèque / structure, alors il y a des chances que vous utilisiez une version différente à l'exécution où B extends A. Dans ma vie, j'avais en fait besoin de faire des vérifications et des lancers aussi étranges, (A)(Object)bcomme au moment de l'exécution, il était en fait possible d'être vrai.
GotoFinal
1

En utilisant le finalmodificateur 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 Testet Foobarne sont pas compatibles les uns avec les autres:

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 Testn'est pas déclaré final, il est possible qu'une sous-classe de Testimplémente l'interface. Et c'est pourquoi le compilateur autoriserait l'instruction test instanceof Foobardans ce cas.

Nurettin Armutcu
la source