2012-08-03 21 views
9

Obtengo un ClassCastException cada vez que trato de convertir una imagen Buffered (principal) en una AdvancedBufferedImage (hija) que extendí yo mismo, no he reemplazado y he implementó todos los contratistas sin modificarloscasting parent to child - Objeto BufferedImage

Me sale esta excepción cada vez que trato de crear una imagen de AdvancedBufferedImage utilizando un método ImageIO.read().

File file = new file(path); 
AdvancedBufferedImage image = (AdvancedBufferedImage) ImageIO.read(file); 

Parece que no debería haber ningún problema, ¿cuál podría ser el problema?

Respuesta

15

Downcasting como este no está permitido.

La solución preferida sería crear un constructor de AdvancedBufferedImage, tomando una imagen BufferedImage como parámetro. Con eso podrías hacer lo siguiente.

File file = new file(path); 
AdvancedBufferedImage image = new AdvancedBufferedImage(ImageIO.read(file)); 

Aquí el constructor de AdvancedBufferedImage puede decidir cómo convertir correctamente una imagen BufferedImage en una avanzada.

+0

¿Así que sugiere cambiar la relación de AdvancedBufferedImage a BufferedImage, ser HAS A not IS IS A? –

+0

Exactamente. Este enfoque le permite delegar los métodos que no desea implementar usted mismo, y aun así agregar funcionalidades adicionales. Simplemente ajustará la clase existente. –

+6

solo un aviso de que hay una herramienta útil para hacer exactamente eso en eclipse, crear una clase que tenga la instancia de la clase que desea delegar, haga clic derecho en el miembro, 'delegar métodos '. muy útil para grandes clases –

-1

Su abatimiento solo tendrá éxito si el objeto que está tratando de lanzar en realidad es una instancia de la clase a la que está enviando.

4

No se puede convertir una clase PARENT en una clase CHILD a menos que la referencia de la clase PARENT tenga una instancia de clase CHILD o sus clases derivadas.

En su caso, ImageIO.read(file) devuelve una instancia de BufferedImage, que es la clase base. Esto solo funcionará, si ImageIO.read(file) devuelve instancia de AdvancedBufferedImage o sus subclases.

Cuando extiende alguna clase, la clase derivada hereda algunas propiedades de la clase base, sin embargo, la clase base no gana nada. Como resultado de esto, dado que la instancia de la clase derivada tiene todas las propiedades de la clase base, una referencia de la clase base puede contener una instancia de clase derivada, es decir, puede convertir una clase DERIVADA en una clase BASE. Ahora, la clase derivada puede agregar algunas propiedades nuevas y la clase base nunca tiene conocimiento de estas propiedades. Así que un elenco de la clase BASE a DERIVADO es obviamente incorrecto.

3

Downcasting in Java

downcasting no va a trabajar de esta manera. Ver la respuesta en la publicación anterior. Como alternativa, ¿qué tal hacer un método de fábrica estático que tome BufferedImage y devuelva una instancia de su clase construida con el objeto devuelto por ImageIO.read()?

Por ejemplo:

private AdvancedBufferedImage(BufferedImage bi) { 
    // build your AdvancedBufferedImage from bi 
    ... 
} 

public static AdvancedBufferedImage buildABI(BufferedImage bi) { 
    return new AdvancedBufferedImage(bi) 
+0

Veo lo que está tratando de decir, pero en este caso hay parámetros en el contratista para los que no son captadores, Así que también tiene que implementar –

+0

Entonces creo que la composición es una mejor idea que la herencia en su caso. ¿Tiene su clase un objeto propio de BufferedImage en lugar de ampliarlo? – Carl

0

BufferedImageno es unaAdvancedBufferedImage por lo que la conversión falla.

Puede extender la funcionalidad de BufferedImage, pero el método read aún devuelve solo BufferedImage. Casting no fuerza a la referencia a convertirse o comportarse como el tipo deseado.

Es probable que desee envolver un BufferedImage en su clase AdvancedBufferedImage, luego puede pasar y manipular su clase avanzada.

2

En general, no se pueden lanzar clases de padres a clases de niños. Es como forzar a lanzar un Animal a un perro. Un perro es un animal, pero a la inversa no siempre es cierto, por lo que el compilador de Java no le permitirá hacer eso.

Ver object inheritance. se permite

2

abatido, pero debe una instancia real del niño:

class A { 
    String name = "a"; 
    A(){}; 
} 

class B extends A { 
} 

public class Main { 
    public static void main(String[] args) { 
    A a = new B(); // must a b instance 
    B b = new B(); 
    b = (B)a; 
    System.out.println(b.name); 

    } 
} 
Cuestiones relacionadas