Java中Vector子类向上转型问题:子类属性无法打印求助
看起来你碰到了两个典型的Java开发问题:子类特有属性无法打印,以及inserisciLaureati方法没能真正合并集合。咱们一步步来解决:
1. 子类属性不显示的根源与修复
你的StudenteLaureato已经重写了toString方法,理论上多态场景下应该会调用子类的版本,但问题出在对象初始化环节:
在letturaDati方法里,你创建StudenteLaureato时用的是3参数构造函数:
StudenteLaureato s = new StudenteLaureato(st.nextToken(), st.nextToken(), st.nextToken());
这个构造函数只初始化了父类的nome、cognome、matricola,子类的indirizzo和dataLaurea完全没赋值(默认是null),所以打印时这两个字段自然看不到。
修复步骤:
- 先确认你的输入文本每行有5个字段(对应子类的5个属性:姓名、姓氏、学号、地址、毕业日期)
- 修改
letturaDati中的对象创建代码,调用5参数的构造函数:
StudenteLaureato s = new StudenteLaureato( st.nextToken(), st.nextToken(), st.nextToken(), st.nextToken(), st.nextToken() );
这样子类的两个特有属性就会被正确初始化,打印时就能正常显示了。
另外补充一句:你已经正确重写了toString,当Vector<Studente>里存放的是StudenteLaureato对象时,Java的多态机制会自动调用子类的toString,这部分逻辑是没问题的,只要属性有值就会打印出来。
2. inserisciLaureati方法的逻辑错误
这里踩了Java参数传递的坑:Java是值传递,你在方法里给elencoloc赋值:
elencoloc = merger(elencoloc, letturaDati(nomeFileDaLeggere));
这只是改变了方法内部局部变量的引用,外面main方法里的elencoloc根本不会被修改,所以合并后的集合完全没生效。
两种修复方案:
方案一:让方法返回合并后的集合
修改inserisciLaureati方法的返回值:
public Vector<Studente> inserisciLaureati(Vector<Studente> elencoloc, String nomeFileDaLeggere) { return merger(elencoloc, letturaDati(nomeFileDaLeggere)); }
然后在main方法中接收返回的新集合:
// 合并后重新赋值给原变量 elencoloc = reg.inserisciLaureati(elencoloc, "C:\\Users\\Nixon\\Desktop\\archiviolau.txt"); // 再打印一次看看结果 reg.stampaDati(elencoloc);
方案二:直接修改原集合(更简洁)
如果不想创建新集合,直接在传入的集合上添加元素即可:
public void inserisciLaureati(Vector<Studente> elencoloc, String nomeFileDaLeggere) { // 读取新的毕业生数据 Vector<Studente> nuoviLaureati = letturaDati(nomeFileDaLeggere); // 直接添加到原集合里 elencoloc.addAll(nuoviLaureati); }
这样main方法里的原集合会被直接修改,不需要重新赋值。
额外的优化建议
- 尽量用
List接口代替具体的Vector类:Vector是比较老旧的线程安全集合,现在更推荐用ArrayList,如果需要线程安全可以用Collections.synchronizedList或者CopyOnWriteArrayList - 处理IO异常:你的
letturaDati方法没有捕获IOException,编译时会报错,建议用try-with-resources语法自动关闭资源,同时处理异常:
public Vector<Studente> letturaDati(String nomeFileDaLeggere) throws IOException { System.out.println("inizio la lettura"); String rowRead; // try-with-resources会自动关闭in资源 try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(nomeFileDaLeggere)))) { while((rowRead = in.readLine()) != null) { StringTokenizer st = new StringTokenizer(rowRead); StudenteLaureato s = new StudenteLaureato( st.nextToken(), st.nextToken(), st.nextToken(), st.nextToken(), st.nextToken() ); elenco.add(s); } } return elenco; }
- 可以给
StudenteLaureato的3参数构造函数里给indirizzo和dataLaurea设置默认值,避免打印出null
修改完这些后,你的程序应该就能正确打印子类的特有属性,并且合并集合的逻辑也能正常工作了。
内容的提问来源于stack exchange,提问作者Nicola Amadio

