jmu-Java-PTA题解 (exam03-学生信息录入) 网安2312陈卓
问题要求
该程序包含
Person类
属性:int id, String name, String birthDate。注意:定义时需按照顺序从上到下定义。
方法:构造方法(id, name, birthDate), id与birthDate的getter方法, name的getter/setter方法,Eclipse自动生成的tostring。
Student类(继承自Person)
属性:int enrollmentYear, String clazzName。
方法:构造方法(id, name, birthdate, enrollmentYear, clazzName),建议使用super复用Person的构造方法;toString方法(包含两行,第一行为父类的toString方法,第二行为Student类自身属性的toString方法,具体格式见输出样例)
Main类
在main方法中输入一个整数n,然后输入n行数据。每行数据对应一个学生的基本信息,不同属性的数据用一个空格分开。
现在需要对输入的n行学生信息的数据进行处理 :
每行学生信息包含4个数据,分别对应name,birthdate, enrollmentYear,clazzName)。处理时,需先行判断每行的参数个数是否符合要求(应等于4个),如不符合则抛出异常提示信息java.lang.Exception: length error!。如果解析的时候碰到解析异常,则输出相应的异常信息。如果都没有异常,则创建相应的Student对象(注意:Student对象id属性的值为for循环中的下标),然后加入列表。
最后,逐行输出学生列表。(注意:每个学生的信息包含两行)。
输入格式:
输入一个整数n
输入n行学生信息数据
输出格式:
输出学生信息列表,有异常则输出异常信息。
输入样例:
6
Liz 1986-10-10 Y2016 CS
Tom 1978-5-7 2006 Software
Sally 2000-1-3 2018 Net01
Jerry 1988-6-7 2016 Mechanical
Eliza 2001-2-5 2019 Software02
Li 1978-5-7
输出样例:
java.lang.NumberFormatException: For input string: "Y2016"
java.lang.Exception: length error!
Person [id=1, name=Tom, birthDate=1978-5-7]
Student [enrollmentYear=2006, clazzName=Software]
Person [id=2, name=Sally, birthDate=2000-1-3]
Student [enrollmentYear=2018, clazzName=Net01]
Person [id=3, name=Jerry, birthDate=1988-6-7]
Student [enrollmentYear=2016, clazzName=Mechanical]
Person [id=4, name=Eliza, birthDate=2001-2-5]
Student [enrollmentYear=2019, clazzName=Software02]
关键点
- 继承机制的应用:通过Student类继承Person类,实现了代码的复用。Student类可以直接使用Person类中定义的属性和方法,并且通过super关键字在构造方法中调用父类构造方法,完成父类属性的初始化。这体现了 Java 面向对象编程中继承的特性,使得代码结构更加清晰,减少了重复代码,提高了开发效率。
- 异常处理的重要性:在数据处理过程中,使用try-catch语句对可能出现的异常进行捕获和处理。对于输入数据格式错误导致的NumberFormatException(如无法将字符串转换为整数),以及数据个数不符合要求时手动抛出的Exception,都进行了相应的处理。合理的异常处理机制能够增强程序的健壮性,使程序在面对错误输入时不会崩溃,而是给出友好的错误提示,提升用户体验。
- 对象创建与数据处理逻辑:在 NameComparator 和 AgeComparator 的 compare 方法中,根据不同的属性(name 和 age)实现了具体的比较逻辑。对于 name 的比较,使用了 String 类的 compareTo 方法;对于 age 的比较,直接进行数值相减。正确的比较逻辑是实现准确排序的核心。
- 排序操作的调用:在Main类的main方法中,按照特定的逻辑进行学生对象的创建和数据处理。先从控制台读取学生信息数据,然后对每行数据进行解析和验证,确保数据合法后创建Student对象并添加到列表中。这种严谨的数据处理流程保证了程序处理数据的准确性,在实际开发中处理大量用户输入数据时具有重要的借鉴意义。
- 方法重写的实现:Student类重写了toString方法,按照题目要求的格式输出学生信息。重写方法时,先调用父类的toString方法输出父类的属性信息,再添加自身属性的信息,保证了输出格式的规范性和完整性。这体现了 Java 中方法重写的特性,使得子类可以根据自身需求对父类方法进行个性化实现 。
解题步骤
第一步:编写 Person 类
定义Person类,包含私有属性id、name和birthDate。提供构造函数用于初始化属性,同时实现id与birthDate的getter方法、name的getter/setter方法,并使用 Eclipse 自动生成toString方法。
class Person{
private int id;
private String name;
private String birthDate;
public Person(int id, String name, String birthDate){
this.id = id;
this.name = name;
this.birthDate = birthDate;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getBirthDate() {
return birthDate;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [" +
"id=" + id +
", name=" + name +
", birthDate=" + birthDate +
']';
}
}
第二步:编写 Student 类
创建Student类继承自Person类,添加私有属性enrollmentYear和clazzName。在构造函数中使用super关键字调用父类构造方法初始化继承的属性,并重新实现toString方法,按要求格式输出学生信息。
class Student extends Person{
private int enrollmentYear;
private String clazzName;
public Student(int id, String name, String birthDate, int enrollmentYear, String clazzName) {
super(id, name, birthDate);
this.enrollmentYear = enrollmentYear;
this.clazzName = clazzName;
}
@Override
public String toString() {
return super.toString() + '\n' + "Student [" +
"enrollmentYear=" + enrollmentYear +
", clazzName=" + clazzName +
']';
}
}
第三步:编写 main 方法
在main方法中,通过Scanner读取输入的学生数量n,再循环读取n行学生信息数据。对每行数据进行处理,判断数据个数是否为 4,若不符合则抛出异常;若符合则尝试创建Student对象,过程中捕获可能出现的解析异常。最后输出学生列表。
public class Main {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
in.nextLine();
Student[] students = new Student[n+1];
for(int i=0; i<n; i++){
String e = in.nextLine();
String[] words = e.split(" ");
try{
if(words.length != 4){
throw new Exception("length error!");
}else{
students[i] = new Student(i, words[0], words[1], Integer.parseInt(words[2]), words[3]);
}
} catch (NumberFormatException ex){
System.out.println(ex);
} catch (Exception ex) {
System.out.println(ex);
}
}
for(int i=0; i<students.length; i++){
if(students[i] != null){
System.out.println(students[i]);
}
}
}
}
整体流程图:
整体代码:
import java.util.*;
class Person{
private int id;
private String name;
private String birthDate;
public Person(int id, String name, String birthDate){
this.id = id;
this.name = name;
this.birthDate = birthDate;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getBirthDate() {
return birthDate;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person [" +
"id=" + id +
", name=" + name +
", birthDate=" + birthDate +
']';
}
}
class Student extends Person{
private int enrollmentYear;
private String clazzName;
public Student(int id, String name, String birthDate, int enrollmentYear, String clazzName) {
super(id, name, birthDate);
this.enrollmentYear = enrollmentYear;
this.clazzName = clazzName;
}
@Override
public String toString() {
return super.toString() + '\n' + "Student [" +
"enrollmentYear=" + enrollmentYear +
", clazzName=" + clazzName +
']';
}
}
public class Main {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
in.nextLine();
Student[] students = new Student[n+1];
for(int i=0; i<n; i++){
String e = in.nextLine();
String[] words = e.split(" ");
try{
if(words.length != 4){
throw new Exception("length error!");
}else{
students[i] = new Student(i, words[0], words[1], Integer.parseInt(words[2]), words[3]);
}
} catch (NumberFormatException ex){
System.out.println(ex);
} catch (Exception ex) {
System.out.println(ex);
}
}
for(int i=0; i<students.length; i++){
if(students[i] != null){
System.out.println(students[i]);
}
}
}
}
思考:该问题中继承机制在代码中起到了关键作用,Student类通过继承Person类,不仅复用了Person类中关于id、name和birthDate的属性与相关方法,还能根据自身需求扩展enrollmentYear和clazzName属性以及特定方法。这种设计使得代码的结构更加清晰,减少了重复代码的编写,同时也体现了 “is-a” 的关系,即学生是一个人,符合现实世界的逻辑关系。这不仅提高了代码的可维护性,也为后续可能的功能扩展提供了便利,比如可以在Person类中添加通用方法,Student类自动就可以使用。异常处理机制的运用也让程序的稳定性得到了极大提升。在处理用户输入时,由于用户输入的不确定性,可能会出现各种错误,例如输入的入学年份无法转换为整数,或者输入的数据个数不符合要求。通过try-catch语句块,程序能够捕获NumberFormatException和自定义的Exception,并给出相应的错误提示。这避免了程序因为异常而突然崩溃,使得程序在面对错误输入时依然能够保持运行,并告知用户错误原因。这种处理方式在实际开发中尤为重要,因为用户输入的不可控性是普遍存在的,良好的异常处理能够提升用户体验,增强程序的可靠性。此外,方法重写的实现使得Student类能够按照特定格式输出信息。通过重写toString方法,先调用父类的toString获取父类属性信息,再添加自身属性信息,保证了输出结果既包含了继承自父类的关键信息,又展示了自身特有的属性,满足了题目对于输出格式的要求。这体现了 Java 中多态性的特性,即不同的对象可以对同一方法做出不同的响应,可以增强代码的灵活性和扩展性。