2011-11-22 11 views
5

¿Alguien puede explicar lo que está pasando aquí?java casting con referencia de superclase

Supongamos Car y Bike son subclases de Vehicle.

Me parece que Vehicle v referencia se lanza a Bike. Sé que esto es ilegal y de hecho el compilador escupe ... Car cannot be cast to Bike.

¿Pero no debería ser Vehicle no se puede convertir a Bike? Después de todo, Vehicle v es una referencia Vehicle.

public class Test { 
    public static void main(String[] args) { 
     Vehicle v = new Car(); 
     Bike b = (Bike) v; 
     // some stuff 
    } 
} 
+1

Porque JVM sabe que es un automóvil cuando lanza la excepción. –

+0

El compilador no divide la excepción. El código arroja un ** tiempo de ejecución ** 'ClassCastException'. –

+0

@Mamá embarazada, acepte una respuesta si está satisfecho con alguno de ellos. – Reddy

Respuesta

3

El mensaje de error dice Car porque esta es la excepción de tiempo de ejecución. Como en este momento conoce la instancia real (automóvil, bicicleta o vehículo) a la que apunta la referencia del vehículo, le da un mensaje de error más específico.

Si esta es una excepción en tiempo de compilación, el compilador habría mencionado Vehicle ya que el compilador puede no conocer la instancia real a la que apunta la referencia del Vehículo.

+0

¡Tiene sentido! Gracias. – m0therway

1

Es realmente un Car que se está emitiendo. v es del tipo Vehicle por lo que la asignación de Vehicle v = new Car(); funciona desde Car es Vehicle.

El objeto v conserva su identidad; que es un Car. Entonces el reparto ilegal es de Car a Bike.

0

La línea

Bike b = (Bike) v; 

sería legal si, por ejemplo, fue un v pasado en Vehicle. Así que supongo que esta validación está sucediendo en el proceso de optimización. El compilador desea optimizar el trabajo normal en el molde si puede, incluso puede optimizar b en total, y por supuesto podría si v se hubiera creado como Bike en la línea anterior, en lugar de Car.

+0

Para ser pedante, esa línea es válida si y solo si v es un objeto Bike (o instancia de una subclase) independientemente de dónde provenga el objeto v. –

0

A (semi) plain-Inglés respuesta:

un coche no puede de repente "se convierten en" una bicicleta o ser tratado como una bicicleta, ya que la bicicleta podría tener diferentes propiedades (variables) describir ella, y diferente maneras de interactuar con él (métodos).

Sin embargo, ambos son vehículos, por lo que tendrían algunas cosas en común, como, tal vez, la capacidad de conducir, girar a la izquierda o derecha, o cambiar de marcha.

Esto hace que sea sencillo cuando se tiene la lógica de esta manera:

ArrayList<Vehicle> vehicles = new ArrayList<Vehicle>(); 
vehicles.add(new Bike()); 
vehicles.add(new Car()); 
vehicles.add(new Bike()); 

//Some other crazy code 

for(Vehicle v : vehicles) { 
    v.applyBrakes(); 
    v.changeDownGear(); 
    v.turnRight(); 
} 

cada subclase de vehículo (bicicleta, coche, Segway, etc.) tendrían su propia aplicación de esos métodos y manejarse apropiadamente

0

Sin el código fuente, es imposible decir de manera definitiva qué es legal y qué no.Sin embargo, es seguro asumir que el árbol de herencia para estas clases se ve algo como

Vehicle 
     | 
    __________ 
    |   | 
Car  Bike 

De tal manera que Car y Bike son subclases de VehicleVehicle lo que significa que es una generalización de Car y Bike. En Java, puede convertir una instancia de una subclase en su clase base. Entonces, en este caso, puede lanzar un Car a un vehículo y tratarlo como si realmente tuviera una instancia de un objeto Vehicle. Lo mismo es cierto con un Bike. Sin embargo, como Car no es una subclase de Bike, no se puede convertir de uno a otro. Todos Cars son Vehicles pero no todos Vehicles son Cars. Tampoco son Bikes. Y un Car nunca es un Bike y viceversa.

Haga esto para crear un código que sea más extensible. Por ejemplo, puede escribir código que comprenda cómo interactuar con el código que se escribirá en el futuro. Un ejemplo de esto sería una interfaz común, como drive(), que permite a otros desarrolladores proporcionar implementaciones personalizadas más adelante. Sin embargo, su código, escrito anteriormente, aún puede funcionar con él, ya que puede tratar las nuevas subclases como si fueran instancias de la clase base.