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
相关产品推荐
相关产品推荐

