2010-10-09 5 views
6

En el siguiente código, el tipo de x es I (aunque x también implementa J pero no se conoce en tiempo de compilación) así que ¿por qué el código en (1) no da como resultado un error de tiempo de compilación. Porque en tiempo de compilación solo se considera el tipo de referencia.¿Por qué funciona este código de instancia de y no causa un error de tiempo de compilación?

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 al margen: no olvide agregar una etiqueta para el idioma. Añadí "java" para ti. – EboMike

+0

lo siento, debería tener – user439526

Respuesta

12

instanceof se utiliza para determinar el tipo de un objeto en tiempo de ejecución. Está intentando determinar si x es realmente un objeto del tipo J cuando el programa se está ejecutando, por lo que se compila.

¿Pensaba que debería generar un error en tiempo de compilación porque cree que el compilador no conoce el tipo x?

Editar

Como Kirk Woll ha comentado (gracias Kirk Woll!), Si estuviera mirando si x es un instanceof una clase concreta, y el compilador puede determinar x 's tipo, por lo que recibirá un error en el tiempo de compilación.

A partir de la especificación del lenguaje Java:

Si un molde de la RelationalExpression a la ReferenceType sería rechazado como un error de compilación, entonces la expresión relacional instanceof asimismo produce un error en tiempo de compilación. En tal situación, el resultado de la instancia de expresión nunca podría ser cierto.

Como un ejemplo de esto:

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, y si * no fuera * un operador en tiempo de ejecución, ¿qué demonios sería el objetivo? Las declaraciones 'if' que lo usan no tendrían sentido. –

+0

Bueno, por lo que he leído hay una verificación de tiempo de compilación inicial cuando se utiliza el operador instanceof que determina si la fuente y el destino tienen una relación subtipo-supertipo. Entonces, el objeto real de la fuente se usa para determinar si la fuente es un subtipo del tipo de Destino. – user439526

+1

Corrija mi comprensión sobre cómo debería funcionar esto. Entonces, en este código, aunque el objeto al que se refiere x es un subtipo de J, pero no hay relación entre I y J. Entonces, como x es de tipo I en el código anterior, es decir, I x = nueva D(); un rol en tiempo de compilación? – user439526

2

instanceof es un operador de tiempo de ejecución, no en tiempo de compilación, por lo que está siendo evaluada utilizando el tipo real del objeto se hace referencia.

+0

Pero puede producir errores de compilación. .. – EJP

+0

Sí, si obtiene entrada estática (es decir, clases en lugar de referencias). Debería editar mi respuesta, aunque kuropenguin ya dio una respuesta muy exhaustiva, así que eso es discutible. – EboMike

Cuestiones relacionadas