第一次博客作业
一、前言
在过去几周的Java编程学习中,通过三组题目集的练习,我逐步深入掌握了从基础语法到面向对象编程、数据结构、异常处理,以及输入输出操作等多个核心概念。这些练习不仅加强了我的基础编程技巧,还逐步引入了更复杂的数据结构和算法应用,使我的编程能力和问题解决技巧得到了显著提升。
题目集1共有5道题,着重于Java基础,涉及类的设计与创建、对象实例化、方法实现及类、数组的基本运用、ArrayList的运用、还有关联类的基本使用原则。
题目集2共有4道题,在题目集1的基础上提升了难度,主要有Comparable接口的实现、类与对象的应用、还涉及ArrayList以及HashMap的运用。
题目集3共有3道题,进一步扩展了面向对象的概念,包括继承、多态和封装、日期类的基本使用、异常处理和IO操作、还涉及List以及HashMap的运用。
二、设计与分析
题目集1的最后一题分析
设计类图与时序图如下
本题的设计思路是实现一个简单的问答系统,它能够让用户输入一系列问题和答案,然后提交答案,系统会验证答案的正确性并给出反馈。系统由三个主要的类组成:Question、Paper和Answer。
- Question类:表示单个问题,包含问题顺序、问题内容和正确答案。它还包含一个方法来检查给定的答案是否正确。
- Paper类:代表一套试卷,用于管理多个Question对象。它提供了添加问题的方法和获取排序后的问题列表的方法。
- Answer类:用于收集用户的答案并验证答案的正确性。它存储了答案和对应的结果,并提供了一个方法来打印问题和用户的答案以及验证结果。
运行流程:
• 通过Scanner类读取用户输入的问题数量,然后循环读取每个问题的具体信息,并创建Question对象存入Paper对象中。
• 用户提交答案时,通过AnswerCollection方法收集答案,并存储在Answer对象中。
• 使用checkAnswers方法验证每个答案的正确性,并将结果存储在results列表中。
• 最后,使用print方法输出每个问题的题目和用户的答案,以及答案的正确与否。
题目集2的最后一题分析
设计类图与时序图如下
本题的设计思路是实现一个更复杂的考试系统,其中包括多个试卷、问题和答案,在题目集1的基础上增加了questionScores映射,用于存储每个问题及其对应分数。这允许系统计算每个问题的分数,并在最后计算总分。还增加了printAlertIfNecessary方法,用于检查试卷的总分是否为100分。如果不是,将打印一条警告信息。该系统能够处理试卷的创建、问题的添加、学生答案的收集、答案的校验以及分数的计算。系统由四个主要的类组成:Question、Paper、Answer和一个主类Main。
- Question类:表示单个问题,包含问题顺序、问题内容和正确答案。它还包含一个方法来检查给定的答案是否正确。
- Paper类:代表一套试卷,用于管理多个Question对象。它提供了添加问题的方法、根据问题顺序获取排序后的问题列表的方法以及计算分数的方法。
- Answer类:用于收集学生的答案并验证答案的正确性。它存储了答案和对应的结果,并提供了一个方法来打印问题、学生的答案以及验证结果。
- Main类:作为程序的入口点,负责读取输入、创建试卷、添加问题、收集答案、校验答案并输出结果。
运行流程:
• 使用Scanner类读取控制台输入,处理包括试卷编号、问题顺序、问题内容、正确答案和学生答案等信息。
• 通过Paper类管理试卷,addQuestion方法用于向试卷中添加问题,同时记录每个问题的分数。getQuestionsSorted方法确保问题按顺序排列。
• Answer类负责收集答案并通过checkAnswers方法校验答案的正确性,结果存储在results列表中。
• Paper类的calculateScores方法根据学生的答案和每道题的分数计算总分,并可通过printAlertIfNecessary方法检查试卷总分是否为100分,如果不是,则打印警告信息。
• 在处理输入时,代码通过判断currentPaper是否存在来避免NullPointerException。
• 在所有答案处理完毕后,Answer类的print方法用于输出每个问题的题目、学生的答案以及答案的正确与否。同时,calculateScores方法输出学生的总分。
整体上,代码可实现试卷和问题的灵活管理,允许动态添加问题和试卷,可实现答案的收集和校验,还提供了基本的测试评分功能。通过面向对象的方法将考试系统的各个组成部分进行了有效的封装和模块化,使得每个类的职责明确,易于理解和维护。然而,代码的实际运行和性能还需要进一步的测试和优化,以确保在各种输入情况下都能正确运行。
题目集3的最后一题分析
设计类图与时序图如下
本题的设计思路是实现一个综合的考试系统,能够处理复杂的考试流程,包括题目管理、试卷创建、学生信息管理、答案收集与评分。系统采用面向对象的方法,将不同的功能封装在不同的类中,以提高代码的可读性和可维护性。以下是各个类的设计思路:
- Question类:该类代表单个考试题目,包含题目的ID、内容和正确答案,以及一个标识题目是否有效的布尔值。它提供了方法来检查答案的正确性,并能标记题目为无效。
- Paper类:代表一套试卷,包含题目列表、题目顺序和题目分数的映射。它提供了添加题目、获取排序后题目列表和计算分数的方法。printAlertIfNecessary方法用于在试卷总分不为100分时打印警告信息。
- Answer类:用于处理学生的答案,包括答案的收集和校验。它存储了答案和校验结果,并提供了方法来打印每个问题的答案和校验结果。
- ExamSystem类:是整个考试系统的中枢,负责管理所有的题目、试卷、学生信息和答案。它提供了添加题目、删除题目、添加试卷、添加学生信息和处理答案的方法。run方法是程序的入口点,负责读取输入并根据输入类型执行相应的操作。
- Main类:包含main方法,是程序的入口。它创建ExamSystem的实例并调用run方法来启动整个系统。
运行流程:
• 系统启动后,通过ExamSystem类的run方法读取用户的输入。
• 根据输入的指令,执行添加题目、添加试卷、添加学生信息、处理答案等操作。
• 答案处理完毕后,调用processAllAnswers方法来计算分数并输出每个学生的答案和得分情况。
三、采坑心得
在提交源码的过程中,我遇到了以下问题:
1.正则表达式运用不熟练
在做题目集1时,对正则表达式的运用还不太了解,导致在字符串分割获取题目序号、题目内容及答案时,老是出现分割不准确问题。以分割题目序号为例:
由于输入格式为#N:1 #Q:1+1= #A:2
序号后面有一个空格,导致不能从String类型转换为int类型,因此需要.trim()来去除字符串两端空白字符后再将字符串转换为int。
当获取题目内容及答案时,若未进行正确的正则表达式操作则会出现格式错误!
2.排序问题
在题目集2中,最初我没有正确地按照试卷题目顺序实现问题排序,导致问题与答案不对应。后面增加了问题排序类后,解决了这个问题。
public List<Question> getQuestionsSorted() {
List<Question> questionsSorted = new ArrayList<>();
for (int order : questionOrders) {
for (Question question : questions) {
if (question.getOrder() == order) {
questionsSorted.add(question);
break;
}
}
}
return questionsSorted;
}
3.NullPointerException异常
在题目集2中,当答卷缺失部分答案或为无效的试卷号时就会抛出NullPointerException,这是因为访问或操作的对象是一个null对象。不过此问题目前还没有解决,后面会努力解决的!
4.失效提示
在题目集3中,一开始删除题目这一部分老是通过不了,因为当题目被删除后,输出时需显示the question x invalid~0,在计算总分时也会导致相应的改变(所删除题目分数为0),删除题目的实现主要由两部分代码组成:
Questin类中
public void invalidate() {
this.isValid = false;
}
ExamSystem类中
public void deleteQuestion(String info) {
int id = Integer.parseInt(info.split("-")[1].trim());
Question q = allQuestions.get(id);
if (q != null) {
q.invalidate();
}
else {
System.out.println("non-existent question~0");
}
}
四、改进建议
题目集2最后一题:
需改进NullPointerException异常问题
这个异常是在Paper.addQuestion方法调用时抛出的,这就意味着传递给addQuestion方法的参数之一是null。
为了解决这个问题,可以采取以下措施:
- 确保对象初始化:在调用addQuestion之前,确保所有需要的对象都已经正确初始化。确保Question对象q不是null,并且Paper对象paper也已经正确创建并初始化。
- 参数校验:在addQuestion方法中添加参数校验,确保传入的Question对象不是null。如果是null,则不执行添加操作或抛出一个更具体的异常来指明问题所在。
public void addQuestion(Question question, int score) {
if (question == null) {
throw new IllegalArgumentException("Question cannot be null");
}
questions.add(question);
questionOrders.add(question.getOrder());
questionScores.put(question.getOrder(), score);
}
确定问题所在后,再通过需求进一步优化代码!
这个NullPointerException异常是在Answer类的checkAnswers方法中抛出的,具体是在Main.java的第96行。要解决这个问题,我们需要确保在调用checkAnswers方法之前,Answer类中的所有对象都已经被正确初始化,不是null。以下是改进措施:
在main()方法中的switch (parts[0]){}里的case "#S":Paper currentPaper = papers.get(answerPaperId);后面增加以下代码即可解决
if (currentPaper == null) {
System.out.println("The test paper number does not exist.");
break;
}
题目集3最后一题:
此需要改进的地方还有很多,以下是改进方向:
- 处理不存在的题目引用:
当试卷引用了不存在的题目时,应输出“non-existent question~0”。需要在Paper类中添加代码以处理这种情况。 - 处理答案数量与试卷题目数量不匹配的情况:
当答案数量少于试卷的题目数量,缺失的答案处应输出“answer is null”。需要在Answer类中添加代码以处理这种情况。 - 处理学号引用错误:
如果答卷中的学号不在学生列表中,应在输出判分信息时提示错误。需要在ExamSystem类中添加代码以检查学号是否存在。 - 优化Paper类的calculateScores方法:
确保在计算分数时,只有有效的答案才会被计分。如果题目被删除或不存在,相应的分数应为0。 - 优化学生信息的处理:
在ExamSystem类中,确保学生信息被正确处理,并且在输出判分信息时,能够正确地关联学生ID和姓名。
五、总结
通过这三次的题目集,我深刻体会到了Java编程的挑战性,三次大作业难度逐步提升,尽管分数不太理想,但在做题和后续优化代码的过程中,我学到了不少东西:对正则表达式运用有了更深刻的理解、对ArrayList、HashMap等数据结构有了更熟练的运用。面向对象设计方面,我更加熟悉了如何定义类、创建对象以及如何通过实例方法和类方法来实现功能,对封装、继承和多态等核心概念有了更深入的认识。这些经验让我在编写和理解代码时更加得心应手!此外,我还意识到了代码的可读性和可维护性的重要性,学会了如何编写更清晰、更模块化的代码,为后续优化代码时理解源代码提供了极大帮助。
在未来的学习中,希望我能有更强的动手能力,在题目中不断实践和应用所学的知识,以逐步提高编程技能和解决问题的能力。