2015-07-14 13 views
85

Vorrei sapere in merito al seguente comportamento dell'operatore instanceof in Java.L'operatore 'instanceof' si comporta in modo diverso per interfacce e classi

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

Perché è così? Non esiste alcuna relazione tra interface C e class B, ma fornisce false mentre in caso di obj instanceof A viene visualizzato un errore del compilatore?

+12

Nota: se lo si modifica in 'Oggetto obj = new B()', viene compilato. – immibis

+1

Cosa dice il compilatore Errore? – karfau

+0

Se 'classe B' è' finale' allora 'obj instanceof C' non verrà compilato neanche, perché se' B' non può avere sottotipi, allora è garantito che non è correlato a 'C'. – jaco0646

risposta

122

Poiché Java non ha ereditarietà di più classi, è assolutamente noto durante la compilazione che l'oggetto obj di tipo B non può essere sottotipo di A. D'altra parte, eventualmente, può sottotipo di interfaccia C, per esempio in questo caso:

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

Così guardando solo obj instanceof C espressione compilatore non può dire in anticipo se sarà vero o falso, ma guardando obj instanceof A esso sa che questo è sempre falso, quindi privo di significato e ti aiuta a prevenire un errore. Se si vuole ancora avere questo controllo senza senso nel programma, è possibile aggiungere un cast esplicito al Object:

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

L'altro aspetto di un controllo privo di significato è l'uso di 'A.class.isAssignableFrom (obj.getClass())' –

+0

Sono un po 'confuso con la tua spiegazione hai detto 'Java non ha ereditarietà multipla di classe' sì Sono d'accordo ma come è applicato in questo caso perché né B né A si estende così tanto perché qui l'eredità multipla. Sarebbe utile se potesse spiegare? – codegasmer

+0

@codegasmer Risposta tardiva: se Java consentiva a una classe di ereditare da più classi, allora si poteva fare "la classe D estende A, B" o alcune di esse, e quindi "B obj = new D()", e fare il " obj instanceof A "nella domanda originale compilare (mentre attualmente non lo fa) - in effetti è meglio compilare, perché dovrebbe essere valutato come vero. Ma se semplicemente non è permesso che qualsiasi cosa sia sia B che A, allora l'espressione "obj instanceof A" dove obj è definita come tipo B può essere ragionevolmente considerata priva di senso. – mjwach

0

Usando il final modificatore nella dichiarazione della classe di seguito, è garantito che non ci potrebbe essere una sottoclasse di Test, che può implementare l'interfaccia Foobar. In questo caso, è evidente che Test e Foobar non sono compatibili tra loro:

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

Altrimenti, se non è dichiarata Testfinal, potrebbe essere possibile che una sottoclasse di Test implementa l'interfaccia. Ed è per questo che il compilatore consentirebbe la dichiarazione test instanceof Foobar in questo caso.

Problemi correlati