Der Operator 'instanceof' verhält sich für Schnittstellen und Klassen unterschiedlich


88

Ich würde gerne wissen, wie sich der instanceofOperator in Java verhält.

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

Wieso ist es so? Es gibt keine Beziehung zwischen interface Cund class B, aber es gibt falsch, während im Falle, wenn es obj instanceof ACompilerfehler gibt?


12
Hinweis: Wenn Sie es ändern, Object obj = new B()wird es kompiliert.
user253751

1
Was sagt Ihnen der Compiler-Fehler?
karfau

If class Bis wird finaldann obj instanceof Cauch nicht kompiliert, da if Bkeine Subtypen haben kann, ist garantiert, dass es keine Beziehung zu hat C.
jaco0646

Antworten:


127

Da Java keine Vererbung mehrerer Klassen hat, ist während der Kompilierung absolut bekannt, dass ein objObjekt vom Typ Bkein Subtyp sein kann A. Andererseits kann es möglicherweise ein Subtyp der Schnittstelle sein C, zum Beispiel in diesem Fall:

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

Wenn Sie also nur den obj instanceof CAusdrucks-Compiler betrachten, können Sie nicht im Voraus sagen, ob er wahr oder falsch ist. Wenn obj instanceof ASie ihn jedoch betrachten , wissen Sie, dass dies immer falsch und somit bedeutungslos ist, und Sie können einen Fehler vermeiden. Wenn Sie diese bedeutungslose Prüfung dennoch in Ihrem Programm haben möchten, können Sie dem Object:

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

1
Der andere Geschmack eines bedeutungslosen Schecks ist zu verwendenA.class.isAssignableFrom(obj.getClass())
David Ehrmann

Ich bin ein bisschen verwirrt mit Ihrer Erklärung. Sie sagten: Java has no multiple class inheritanceJa, ich stimme zu, aber wie wird es in diesem Fall angewendet, weil weder B noch A irgendetwas erweitern. Warum also Mehrfachvererbung hier? Es wäre hilfreich, wenn Sie es erklären können.
Codegasmer

@codegasmer Späte Antwort: Wenn Java einer Klasse erlaubt, von mehreren anderen Klassen zu erben, könnte man "Klasse D erweitert A, B" oder ähnliches und dann "B obj = new D ()" ausführen und das "obj" erstellen Instanz von A "in der ursprünglichen Frage kompilieren (während dies derzeit nicht der Fall ist) - tatsächlich sollte es besser kompiliert werden, da erwartet wird, dass es als wahr bewertet wird. Wenn es jedoch einfach nicht erlaubt ist, dass irgendetwas sowohl B als auch A ist, kann der Ausdruck "obj instanceof A", wobei obj als Typ B definiert ist, vernünftigerweise als unsinnig angesehen werden.
mjwach

"Wenn Sie diese bedeutungslose Prüfung immer noch durchführen möchten" - sie muss nicht bedeutungslos sein, da diese Klassen aus einer anderen Bibliothek / einem anderen Framework stammen, besteht die Möglichkeit, dass Sie zur Laufzeit eine andere Version verwenden B extends A. In meinem Leben musste ich tatsächlich so seltsame Überprüfungen und Besetzungen durchführen, wie es (A)(Object)bzur Laufzeit tatsächlich möglich war, wahr zu sein.
GotoFinal

1

Durch die Verwendung des finalModifikators in der folgenden Klassendeklaration wird garantiert, dass es keine Unterklasse von geben kann Test, die die Schnittstelle implementieren kann Foobar. In diesem Fall ist es offensichtlich, dass Testund Foobarnicht miteinander kompatibel sind:

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

Andernfalls kann es vorkommen, dass eine Unterklasse von die Schnittstelle implementiert , wenn sie Testnicht deklariert finalist Test. Und deshalb würde der Compiler die Anweisung test instanceof Foobarin diesem Fall zulassen .

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.