2010-02-10 13 views
18

¿Cuándo se puede lanzar un determinado objeto a otro objeto? ¿El objeto casted debe ser un subtipo del otro objeto? Estoy tratando de descubrir las reglas ...Reglas de Java para fundición

Editar: Me di cuenta de que no explicaba mi problema en absoluto: básicamente estoy lanzando un objeto a un tipo de interfaz. Sin embargo, en tiempo de ejecución, obtengo un java.lang.ClassCastException. ¿Qué necesita pasar con mi objeto para poder lanzarlo a esta interfaz? ¿Tiene que implementarlo?

Gracias

+0

En qué situación es lo que realmente necesita para convertirse explícitamente un objeto a su tipo de interfaz? – harto

+0

Tiene una respuesta muy útil aquí. Desearía que lo seleccionaras. – orbfish

Respuesta

1

puede convertir si el tipo de tiempo de ejecución de un objeto es un subtipo de lo que estamos tratando de echar en.

EDIT:

Sí, el objeto que usted está tratando de echar tendrán que implementar la interfaz con el fin de que usted eche con éxito.

+0

Estás pensando en esto completamente de la manera incorrecta. Lo que debería preguntar es "¿en qué situaciones tiene sentido tratar este' Foo' como un 'IBar'? –

+0

¿Qué sucede si el objeto que intento convertir a esa interfaz amplía una clase que implementa la interfaz? ¿evitará eso el error de tiempo de ejecución? – alan

+0

oh ok..i intenté reformular mi comentario original, ya que realmente no tenía sentido en el primer intento – alan

27

En Java existen dos tipos de referencia de fundición variables:

  • downcasting: Si usted tiene un variable de referencia que hace referencia a un objeto subtipo , se puede asignar a una variable referencia del subtipo. Debe hacer una conversión explícita para hacer esto, y el resultado es que puede acceder a los miembros del subtipo con esta nueva variable de referencia.

  • upcasting: Puede asignar una variable de referencia a una referencia supertipo variable de forma explícita o implícita. Esta es una operación inherentemente segura porque la asignación restringe las capacidades de acceso de la nueva variable .

, es necesario implementar la interfaz directa o indirectamente para permitir la asignación de la clase de referencia de objeto al tipo de interfaz.

+0

No estoy seguro de si usted escribió esto, lo copió o resumió, pero es excelente, me hizo darme cuenta de lo que estaba tratando de hacer eso no tiene sentido. – orbfish

+0

ejemplos han sido útiles –

+0

Votos porcentuales debido al texto escrito por humanos, no algunos 'B extiende la charla A'. –

1

Si:

interface MyInterface{} 

class MyClass implements MyInterface{} 

Entonces

MyClass m = new MyClass(); 
MyInterface i = (MyInterface)m; 

es posible.

2

Hay una forma intuitiva de pensar sobre esto: no está cambiando un objeto con un molde, solo está haciendo algo que ya estaría permitido si el tipo se conoce, en otras palabras, solo puede convertir a un tipo que tu objeto ya es Así que simplemente busque "arriba" la cadena de objetos para ver qué tipos se aplican a su objeto.

Así que puede convertir a una interfaz solo si está definida en algún lugar más arriba de la cadena (por ejemplo, si el padre de la clase lo implementa, etc., etc.).Tiene que ser explícito: a partir de su pregunta, parece que puede estar pensando que si implementa el método "void foo()", entonces debería poder enviar a una interfaz que defina el método "void foo()" - esto es a veces se describe como "duck typing" (si grazna como un pato, es un pato) pero no es así como funciona Java.

3

Esto funcionará:

class Foo implements Runnable { 
    public void run() {} 
} 

Foo foo = new Foo(); 
System.out.println((Runnable) foo); 

pero esto no será:

class Bar { 
    public void run() {} 
} 

Bar bar = new Bar(); 
System.out.println((Runnable) bar); 

Porque aunque Bar tiene un método run() que podría aplicar Runnable.run(), Bar no se declara a aplicar Runnable por lo que no se puede convertir a Runnable.

Java requiere que declare interfaces implementadas por nombre. No tiene duck typing, a diferencia de otros lenguajes como Python y Go

2

Supóngase que se desea emitir d objeto a A,

A a = (C) d;

Así que internamente 3 reglas han sido comprobadas por el compilador y JVM. El compilador comprueba las 2 primeras reglas en Tiempo de compilación y JVM comprobará la última regla en tiempo de ejecución.

Regla 1 (Tiempo de compilación comprobación):

tipo de 'd' y C debe tener alguna relación (hijo a padre o padre a hijo o mismo tiempo) .Si no hay relación entonces obtendremos un error de compilación (tipos inconvertibles).

Regla 2 (Compilar tiempo comprobando):

'C' debe ser o bien mismo tipo o tipo derivado (subclase) de 'A' si no conseguir un error de compilación (incompatible tipos).

Regla 3 (Excepción Runtime):

Runtime tipo de objeto de 'd' debe ser igual o derivado un tipo de 'C' lo contrario obtendremos una excepción de tiempo de ejecución (ClassCastException Excepción).

Búsqueda siguientes ejemplos para obtener más idea,

String s = new String("hello"); StringBuffer sb = (StringBuffer)s; // Compile error : Invertible types because there is no relationship between. 

Object o = new String("hello"); StringBuffer sb = (String)o;  // Compile error : Incompatible types because String is not child class of StringBuffer. 

Object o = new String("hello"); StringBuffer sb = (StringBuffer)o; // Runtime Exception : ClassCastException because 'o' is string type and trying to cast into StingBuffer and there is no relationship between String and StringBuffer.