You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java子类方法调用异常解决:禁用instanceof处理ClassCastException

解决方案

问题根源

异常的核心原因是readFromFile方法始终创建父类Pergunta的实例,而非对应主题的子类实例。即使area字段标记为PerguntaArtes,实际对象类型仍是Pergunta,强转成子类自然会抛出ClassCastException。

修复步骤(基于多态实现,规避类型判断)

1. 重构父类Pergunta,添加抽象方法

将父类改为抽象类,定义抽象的分数计算方法,让所有子类自行实现:

public abstract class Pergunta {
    private String area;
    private String pergunta;
    private ArrayList<String> opcoes;
    private String respostaCorreta;
    private String dificuldade;
    protected int pontosPergunta;

    public Pergunta(String area, String pergunta, ArrayList<String> opcoes, String respostaCorreta, String dificuldade, int pontosPergunta) {
        this.area = area;
        this.pergunta = pergunta;
        this.opcoes = opcoes;
        this.respostaCorreta = respostaCorreta;
        this.dificuldade = dificuldade;
        this.pontosPergunta = pontosPergunta;
    }

    // 抽象方法:子类必须实现分数计算逻辑
    public abstract int calcularPontuacao();

    // 原有get/set方法保持不变
    public String getPergunta() { return pergunta; }
    public ArrayList<String> getOpcoes() { return opcoes; }
    public void setArea(String area){ this.area=area; }
    public String getArea(){ return this.area; }

    // 后续修改readFromFile方法...
}

2. 完善子类实现

确保所有主题子类都重写calcularPontuacao方法:

  • PerguntaArtes(已实现,无需修改)
public class PerguntaArtes extends Pergunta {
    public PerguntaArtes(String area, String pergunta, ArrayList<String> opcoes, String respostaCorreta, String dificuldade, int pontosPergunta) {
        super(area, pergunta, opcoes, respostaCorreta, dificuldade, pontosPergunta);
    }

    @Override
    public int calcularPontuacao(){
        return pontosPergunta * 10;
    }
}
  • 新增PerguntaCiencias子类
public class PerguntaCiencias extends Pergunta {
    public PerguntaCiencias(String area, String pergunta, ArrayList<String> opcoes, String respostaCorreta, String dificuldade, int pontosPergunta) {
        super(area, pergunta, opcoes, respostaCorreta, dificuldade, pontosPergunta);
    }

    @Override
    public int calcularPontuacao() {
        return 20;
    }
}
  • 新增PerguntaDesporto子类
public class PerguntaDesporto extends Pergunta {
    public PerguntaDesporto(String area, String pergunta, ArrayList<String> opcoes, String respostaCorreta, String dificuldade, int pontosPergunta) {
        super(area, pergunta, opcoes, respostaCorreta, dificuldade, pontosPergunta);
    }

    @Override
    public int calcularPontuacao() {
        return 20;
    }
}

3. 修改readFromFile方法,创建对应子类实例

根据文件中读取的area字段,实例化对应的子类对象:

public static Pergunta readFromFile(String filename) {
    try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
        String line;
        while ((line = br.readLine()) != null) {
            String[] parts = line.split("-");
            String area = parts[0];
            String dificuldade = parts[1];
            String pergunta = parts[2];
            ArrayList<String> opcoes = new ArrayList<>(Arrays.asList(parts[3].split(",")));
            String respostaCorreta = parts[4];
            int pontosPergunta = Integer.parseInt(parts[5]);

            // 根据area创建对应子类实例
            switch(area) {
                case "PerguntaArtes":
                    return new PerguntaArtes(area, pergunta, opcoes, respostaCorreta, dificuldade, pontosPergunta);
                case "PerguntaCiencias":
                    return new PerguntaCiencias(area, pergunta, opcoes, respostaCorreta, dificuldade, pontosPergunta);
                case "PerguntaDesporto":
                    return new PerguntaDesporto(area, pergunta, opcoes, respostaCorreta, dificuldade, pontosPergunta);
                default:
                    // 处理未知主题,可返回null或抛出自定义异常
                    return null;
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

4. 简化checkAnswer方法

利用多态特性,直接调用calcularPontuacao方法,无需任何类型判断:

private void checkAnswer(String selectedOption, String respostaCorreta, Pergunta pergunta){
    if (selectedOption.equals(respostaCorreta)){
        score += pergunta.calcularPontuacao();
    }
    questionnumber += 1;
    if (questionnumber <= 5){
        displayQuestion(questionnumber);
    } else {
        endGame();
    }
}

效果说明

  • 彻底解决ClassCastException:现在readFromFile返回的是对应子类实例,强转不再必要。
  • 符合限制要求:全程未使用instanceof或class.getName(),完全依赖多态实现逻辑分发。
  • 代码更易维护:新增主题只需添加子类并实现calcularPontuacao,无需修改checkAnswer等核心逻辑。

内容的提问来源于stack exchange,提问作者Comicas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 08:58:19