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 中多态性的特性,即不同的对象可以对同一方法做出不同的响应,可以增强代码的灵活性和扩展性。

posted @ 2025-04-25 10:20  取名字比写博客还难  阅读(17)  评论(0)    收藏  举报