2010-10-09 8 views
6

Nel seguente codice, il tipo di x è I (anche se x implementa anche J ma questo non è noto al momento della compilazione), quindi perché è che il codice su (1) non determina un errore di compilazione. Perché al momento della compilazione viene preso in considerazione solo il tipo di riferimento.Perché questa istanza di codice funziona e non causa un errore di compilazione?

public class MyClass { 
    public static void main(String[] args) { 
     I x = new D(); 
     if (x instanceof J) //(1) 
      System.out.println("J"); 
    } 
} 

interface I {} 

interface J {} 

class C implements I {} 

class D extends C implements J {} 
+1

Nota a margine: non dimenticare di aggiungere un tag per la lingua. Ho aggiunto "java" per te. – EboMike

+0

scusa dovrei avere – user439526

risposta

12

instanceof viene utilizzato per la determinazione della fase di esecuzione di tipo di un oggetto. Stai cercando di determinare se x è davvero un oggetto di tipo J quando il programma è in esecuzione, quindi compila.

Pensavate che dovesse causare un errore in fase di compilazione perché pensate che il compilatore non conosca il tipo x?

Modifica

Mentre Kirk Woll ha commentato (grazie Kirk Woll!), Se si dovesse verificare se x è un instanceof una classe concreta, e il compilatore può determinare x s' tipo, allora si otterrà un errore in fase di compilazione.

Dal linguaggio Java Specification:

Se un cast del RelationalExpression al ReferenceType sarebbe stata respinta come un errore di compilazione, quindi l'espressione relazionale instanceof produce anche un errore di compilazione. In una situazione del genere, il risultato dell'istanza di espressione non potrebbe mai essere vero.

Come esempio di questo:

import java.io.Serializable; 
import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.io.ObjectInputStream; 

class SerializableClass implements Serializable 
{ 
    private writeObject(ObjectOutputStream out) {} 
    private readObject(ObjectInputStream in) {} 
} 

public class DerivedSerializableClass extends SerializableClass 
{ 
    public static void main(String[] args) 
    { 
     DerivedSerializableClass dsc = new DerivedSerializableClass(); 

     if (dsc instanceof DerivedSerializableClass) {} // fine 
     if (dsc instanceof Serializable) {} // fine because check is done at runtime 
     if (dsc instanceof String) {} // error because compiler knows dsc has no derivation from String in the hierarchy 

     Object o = (Object)dsc; 
     if (o instanceof DerivedSerializableClass) {} // fine because you made it Object, so runtime determination is necessary 
    } 
} 
+1

+1, e se * non fosse * un operatore di runtime, cosa diavolo sarebbe il punto di esso? Le dichiarazioni di "se" che ne fanno uso non avrebbero senso. –

+0

Bene da quello che ho letto c'è un controllo iniziale della compilazione quando si utilizza l'operatore instanceof che determina se l'origine e la destinazione hanno una relazione tra sottotipo e supertipo. Quindi viene utilizzato l'oggetto effettivo della sorgente per determinare se l'origine è un sottotipo di tipo Destinazione. – user439526

+1

Si prega di correggere la mia comprensione su come dovrebbe funzionare. Quindi in questo codice anche se l'oggetto a cui fa riferimento x è un sottotipo di J ma non esiste alcuna relazione tra I e J. Quindi poiché x è di tipo I nel codice di sopra cioè I x = new D();, dovrebbe essere riprodotto un ruolo in fase di compilazione? – user439526

2

instanceof è un operatore di run-time, non in fase di compilazione, pertanto sono stati valutati utilizzando il tipo effettivo dell'oggetto fa riferimento.

+0

Ma può produrre errori di compilazione. .. – EJP

+0

Sì, se riceve input statico (cioè classi piuttosto che riferimenti). Dovrei modificare la mia risposta, anche se il kuropenguin ha già dato una risposta molto esaustiva, quindi è discutibile. – EboMike

Problemi correlati