Исключение java.lang.ClassCastException при приведении подкласса из суперкласса

#java #exception #casting #subclass #superclass

#java #исключение #Кастинг #подкласс #суперкласс

Вопрос:

Я получаю ошибку в названии, когда пытаюсь использовать метод getInfoDerivada() из Desguace :

Исключение в потоке «main» java.lang.ClassCastException: es.unex.cum.mdp.sesion2.Vehiculo не может быть приведен к es.unex.cum.mdp.sesion2.Moto в es.unex.cum.mdp.sesion2.Desguace.getInfoDerivada(Desguace.java:93) в es.unex.cum.mdp.sesion2.Main.main(Main.java:21)

И я не знаю, как привести подкласс Moto , чтобы использовать его метод getPotencia() из суперкласса Vehiculo .

Спасибо

 package es.unex.cum.mdp.sesion2;

public class Main {

    public static void main(String[] args) {

        Persona p = new Persona();
        Vehiculo v = new Coche("Renault","Asd",p,1234,"azul");
        Vehiculo v1 = new Moto("a","b",p,2345,25);

        if(v.getClass().equals(Coche.class))
            System.out.println("holi 1.0");

        Desguace d = new Desguace("pepe",2);

        if(d.addVehiculo(v))
            System.out.println("ok");
        if(d.addVehiculo(v1))
            System.out.println("ok");

        String a = d.getInfoDerivada(1);
        String b = v1.toString();
        System.out.println(b);

        System.out.println(a);

    }

}
  

Описание класса

 package es.unex.cum.mdp.sesion2;

import java.util.Arrays;

public class Desguace {
    protected String nombre;
    protected Vehiculo [] vehiculos;
    protected Integer cont;


    public Desguace() {
        nombre = "";
        vehiculos = new Vehiculo[0];
        cont = 0;
    }

    public Desguace(String nombre, int cant) {
        this.nombre = nombre;
        vehiculos = new Vehiculo[cant];
        cont = 0;
    }

    public boolean addVehiculo (Vehiculo v){
        for(int i = 0; i < cont; i  )
            if(vehiculos[i].getBastidor() == v.getBastidor())
                return false;
        if(cont<vehiculos.length){
            vehiculos[cont] = new Vehiculo(v);
            cont = cont   1;
            return true;
        }
        else
            return false;
    }

    public Vehiculo getVehiculoBastidor(Integer bastidor){
        if(bastidor < 0)
            return null;
        for(int i = 0; i < cont; i  ){
            if(vehiculos[i].getBastidor()==bastidor)
                return vehiculos[i];
        }
        return null;
    }

    public boolean addPiezaVehiculo(Pieza p, Integer bastidor){
        if(bastidor < 0)
            return false;
        for(int i = 0; i < cont; i  ){
            if(vehiculos[i].getBastidor() == bastidor){
                for(int j = 0; j < vehiculos[i].getCont(); j  ){
                    if(vehiculos[i].getPiezaV(j).equals(p)){
                        vehiculos[i].getPiezaV(j).setContador(vehiculos[i].getPiezaV(j).getContador()   p.getContador());
                        return true;}
                    else{
                        if(vehiculos[i].getCont() < 3){
                            vehiculos[i].addPiezaV(p);
                            vehiculos[i].setCont(vehiculos[i].getCont() 1);
                        }
                        else
                            return false;
                    }
                }

            }
        }
        return false;
    }

    public Vehiculo mayorStock(){
        int aux = 0;
        if(vehiculos[aux] == null)
            return null;
        for(int i = 1; i < cont; i  ){
            if(vehiculos[aux].getCont() < vehiculos[i].getCont())
                aux = i;
        }
        return vehiculos[aux];  
    }

    public String getInfoDerivada(int pos){
        if(pos < 0 || pos >= cont){
            return null;}
        if(vehiculos[pos].getClass() == Coche.class){
            return ((Coche)vehiculos[pos]).getColor();
        }
        if(vehiculos[pos].getClass() == Moto.class){
            return String.valueOf(((Moto)vehiculos[pos]).getPotencia());
        }
        if(vehiculos[pos].getClass() == Camion.class){
            return String.valueOf(((Camion)vehiculos[pos]).getTonelaje());
        }
            return String.valueOf(((Moto)vehiculos[pos]).getPotencia());
    }

    public String getNombre() {
        return nombre;
    }
    public void setNombre(String nombre) {
        this.nombre = nombre;
    }
    public Integer getCont() {
        return cont;
    }
    public void setCont(Integer cont) {
        this.cont = cont;
    }
    public Vehiculo[] getVehiculos() {
        return vehiculos;
    }

    @Override
    public String toString() {
        return "Desguace [nombre="   nombre   "]";
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Desguace other = (Desguace) obj;
        if (cont == null) {
            if (other.cont != null)
                return false;
        } else if (!cont.equals(other.cont))
            return false;
        if (nombre == null) {
            if (other.nombre != null)
                return false;
        } else if (!nombre.equals(other.nombre))
            return false;
        if (!Arrays.equals(vehiculos, other.vehiculos))
            return false;
        return true;
    }



}
  

Класс Vehiculo

 package es.unex.cum.mdp.sesion2;

public class Vehiculo {
    protected String marca;
    protected String modelo;
    protected Persona propietario;
    protected Pieza[] piezas;
    protected Integer bastidor;
    protected Integer cont;

    public Vehiculo() {
        marca = "";
        modelo = "";
        propietario = new Persona();
        bastidor = 0;
        piezas=new Pieza[3];
        for(int i = 0; i < piezas.length; i  )
            piezas[i] = new Pieza();
        cont=0;
    }

    public Vehiculo(String marca, String modelo, Persona p, Integer bastidor) {
        this.marca = marca;
        this.modelo = modelo;
        this.bastidor = bastidor;
        propietario = new Persona(p.getNombre(),p.getDni(),p.getEdad());
        piezas=new Pieza[3];
        for(int i = 0; i < piezas.length; i  )
            piezas[i] = new Pieza();
        cont = 0;
    }

    public Vehiculo(Vehiculo p) {
        this(p.getMarca(),p.getModelo(),p.propietario, p.getBastidor());
    }

    public boolean addPiezaV(Pieza p) {
        for(int i = 0; i < cont; i  ){
            if(piezas[i].equals(p))
                piezas[i].setContador(piezas[i].getContador() p.getContador());
        }
        piezas[cont].setId(p.getId());
        piezas[cont].setNombre(p.getNombre());
        piezas[cont].setContador(p.getContador());
        cont = cont   1;
        return true;

    }

    public Pieza getPiezaV(int pos) {
        if(pos >= piezas.length || pos < 0)
            return null;
        else
            return piezas[pos];


    }
    //getter y setter

    public String getMarca() {
        return marca;
    }

    public void setMarca(String marca) {
        this.marca = marca;
    }

    public String getModelo() {
        return modelo;
    }

    public void setModelo(String modelo) {
        this.modelo = modelo;
    }

    public Integer getBastidor() {
        return bastidor;
    }

    public void setBastidor(Integer bastidor) {
        this.bastidor = bastidor;
    }

    public Integer getCont(){
        return cont;
    }

    public void setCont(Integer cont){
        this.cont = cont;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Vehiculo other = (Vehiculo) obj;
        if (bastidor == null) {
            if (other.bastidor != null)
                return false;
        } else if (!bastidor.equals(other.bastidor))
            return false;
        if (cont == null) {
            if (other.cont != null)
                return false;
        } else if (!cont.equals(other.cont))
            return false;
        if (marca == null) {
            if (other.marca != null)
                return false;
        } else if (!marca.equals(other.marca))
            return false;
        if (modelo == null) {
            if (other.modelo != null)
                return false;
        } else if (!modelo.equals(other.modelo))
            return false;
        if (propietario == null) {
            if (other.propietario != null)
                return false;
        } else if (!propietario.equals(other.propietario))
            return false;
        return true;
    }

}
  

Класс Moto

 package es.unex.cum.mdp.sesion2;

public class Moto extends Vehiculo {
    protected Integer potencia;

    public Moto(){
        super();
        potencia = 0;
    }

    public Moto(String marca, String modelo, Persona p, Integer bastidor, Integer potencia){
        super(marca,modelo,p,bastidor);
        this.potencia = potencia;
    }

    public Integer getPotencia() {
        return potencia;
    }

    public void setPotencia(Integer potencia) {
        this.potencia = potencia;
    }

    @Override
    public String toString() {
        return "Moto[marca="   marca   ", modelo="   modelo   ", bastidor="   bastidor   ", potencia="   potencia  "]";
    }

}
  

Комментарии:

1. используйте instanceof вместо проверки, равны ли классы, другими словами vehiculos[pos].getClass() == Coche.class , должно быть vehiculos[pos] instanceof Coche.class

2. Он по-прежнему возвращает null, и я не знаю почему, похоже, что if никогда не бывает true .

Ответ №1:

Вы можете преобразовать a Moto в a Vehiculo без необходимости что-либо проверять и необходимости приводить его как к Moto подклассу of , Vehiculo но если вы хотите сделать обратное, вам нужно сначала проверить, является ли ваш экземпляр Vehiculo экземпляром Moto using instanceof , потому что экземпляр Vehiculo не нужен, экземпляр Moto которого является основной причинойваша проблема здесь, когда вы получаете ClassCastException . Что еще хуже, согласно вашему сообщению об ошибке, вы пытаетесь привести экземпляр Vehiculo к экземпляру Moto , который просто невозможен.

 if (vehiculos[pos] instanceof Moto) {
    // Here we can safety cast to a moto
    Moto moto = (Moto) vehiculos[pos];
    ...
}
  

Ваша проблема заключается в методе getInfoDerivada , когда вы доходите до последнего случая, вы приводите его к a Moto , чего не может быть, поскольку мы уже знаем, что это не экземпляр Moto .

Ваш код должен быть примерно таким:

 public String getInfoDerivada(int pos){
    if(pos < 0 || pos >= cont){
        return null;
    }
    if(vehiculos[pos] instanceof Coche){
        return ((Coche)vehiculos[pos]).getColor();
    } else if(vehiculos[pos] instanceof Moto){
        return String.valueOf(((Moto)vehiculos[pos]).getPotencia());
    } else if(vehiculos[pos] instanceof Camion){
        return String.valueOf(((Camion)vehiculos[pos]).getTonelaje());
    }
    throw new IllegalStateException(
        String.format("Unknown type: %s", vehiculos[pos].getClass().getName())
    );
}
  

На самом деле ваша ошибка addVehiculo , вы должны назначить непосредственно экземпляр Vehiculo provided вместо создания нового экземпляра Vehiculo с ним.

 public boolean addVehiculo (Vehiculo v){
    ...
    if(cont<vehiculos.length){
        vehiculos[cont] = v;// instead of new Vehiculo(v);
        ...
    }
    ...
}
  

Гораздо лучшим подходом было бы добавить новый метод getInfoDerivada в класс Vehiculo , для которого вы предоставите реализацию по умолчанию, а затем переопределить его в подклассах, если это необходимо, ваш код будет просто:

 public String getInfoDerivada(int pos){
    if(pos < 0 || pos >= cont){
        return null;
    }
    return vehiculos[pos].getInfoDerivada();
}
  

Комментарии:

1. То, что я предлагаю в конце, — это подход OO, так что это путь сюда, поскольку ваш учитель должен знать, что Java — это язык программирования OO

2. Большое вам спасибо, хотя я не мог напрямую назначить экземпляр массиву. Извините за мои ошибки при публикации / редактировании, впервые здесь.