2015-07-14 9 views
85

Ich möchte in Bezug auf folgendes Verhalten von instanceof-Operator in Java wissen.Der 'instanceof'-Operator verhält sich für Schnittstellen und Klassen unterschiedlich

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

Warum ist es so? Es gibt keine Beziehung zwischen interface C und class B, aber es gibt falsch, während im Falle es Compiler Fehler gibt?

+12

Hinweis: Wenn Sie es in 'Object obj = new B()' ändern, wird es kompiliert. – immibis

+1

Was sagt Ihnen der Compiler Fehler? – karfau

+0

Wenn "Klasse B" "final" ist, wird auch "obj instanceof C" nicht kompiliert, denn wenn "B" keine Subtypen haben kann, dann ist garantiert, dass sie nicht mit "C" in Beziehung stehen. – jaco0646

Antwort

122

Da Java keine Mehrfachklassenvererbung besitzt, ist während der Kompilierung absolut bekannt, dass obj Objekt vom Typ B nicht Untertyp A sein kann. Auf der anderen Seite möglicherweise kann es Subtyp der Schnittstelle C, zum Beispiel in diesem Fall sein:

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

sucht also nur bei obj instanceof C Ausdruck Compiler im Voraus nicht sagen kann, ob es wahr oder falsch sein, aber bei obj instanceof A suche es weiß, dass dies immer falsch und damit bedeutungslos ist und hilft dir, einen Fehler zu vermeiden. Wenn Sie immer noch diese sinnlose Prüfung in Ihrem Programm haben wollen, können Sie eine explizite Casting zum Object hinzufügen:

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

Die andere Variante einer sinnlosen Überprüfung ist die Verwendung von 'A.class.isAssignableFrom (obj.getClass())' –

+0

Ich bin etwas verwirrt mit Ihrer Erklärung, Sie sagten 'Java hat keine Mehrfachklassen-Vererbung' Ja stimme ich zu, aber wie es ist in diesem Fall angewendet, weil weder B noch A irgendwas ausdehnt, also warum multiple Vererbung hier. Es wäre hilfreich, wenn du es erklären könntest? – codegasmer

+0

@codegasmer Späte Antwort: Wenn Java einer Klasse erlaubte, von mehreren anderen Klassen zu erben, dann könnte man "Klasse D erweitert A, B" oder so etwas und dann "B obj = neues D()" machen und die " Obj instanceof "in der ursprünglichen Frage kompilieren (während es derzeit nicht) - in der Tat war es besser kompilieren, weil es erwartet werden würde, um zu wahren. Aber wenn es einfach nicht erlaubt ist, dass irgendetwas sowohl B als auch A ist, dann kann der Ausdruck "obj instanceof A", wo obj als Typ B definiert ist, vernünftigerweise als unsinnig angesehen werden. – mjwach

0

Durch die Verwendung des final Modifikator in der Klassendeklaration unten ist gewährleistet, dass es nicht sein kann eine Unterklasse von Test, die die Schnittstelle Foobar implementieren kann. In diesem Fall ist es offensichtlich, dass Test und Foobar miteinander nicht 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, wenn Test nicht final erklärt wird, könnte es möglich sein, dass eine Unterklasse von Test die Schnittstelle implementiert. Und deshalb würde der Compiler in diesem Fall die Anweisung test instanceof Foobar zulassen.