OOP第一次博客作业
前言:
这三次pta大作业是我第一次系统的对java程序进行系统的训练。对我而言,java语法的自学和理解给我带来了很大的困难。由于我之前习惯于C语言的思维方式,所以在编写Java代码时,我的思维转换并不迅速。在完成作业的过程中,我逐渐调整自己的思维方式,以适应Java的编程范式。
与此同时,我意识到学习Java不仅仅是掌握语法,更重要的是理解面向对象编程的思想,这也是老师一直强调的要点。由于我之前对此没有了解,因此在遇到与面向对象相关的题目时,我感到有些陌生。
前三次的题目集主要测试了我们对Java基本语法的掌握程度,以及类的基本用法、类与类之间的关系和单一职责原则的理解。这些题目集共有12道题,其中每次作业的最后一道题都相对较难,并且是在前一次作业的基础上增加了新的功能。在这里我将简单总结一下,前三次pta大作业的知识点、题量、难度等情况:
设计与分析:
- 第一次题目集
首次作业的核心目标是判断答案是否正确,因此在实现时可能更偏向于使用简单直观的方法,例如通过字符串数组来分别存储题目、标准答案和作答内容。这种设计在初次作业中是完全可行的,并且能够快速地完成需求。 但是,如果作业不断地迭代,复杂度逐渐增加,类的使用就变得尤为重要。第二次和第三次作业建立在第一次的基础上,引入类和对象的概念有助于更好地组织和管理代码,提高代码的可读性和可维护性。 具体来说,使用Question类来封装题目信息,包括题号、题目内容和标准答案,可以使得每个题目成为一个独立的实体,方便后续的操作和处理。同样地,Answer类用于封装作答内容,使得作答也成为了一个独立的对象。最后通过定义判断答案与标准答案是否相同的方法,可以实现对作答的自动化处理和输出。 在实现过程中,还需要注意输入数据的格式问题。题目和标准答案之间可能存在多余的空格,这时就需要利用正则表达式来去除这些空格,确保数据的准确性。 总体来说,虽然第一次作业相对简单,但通过使用类和对象的概念进行封装和组织,为后面的作业奠定了坚实的基础,起到了很好的铺垫作用。同时,这也体现了面向对象编程思想在实际应用中的重要性。
sourcemonitor中的报表
PowerDesigner中的类图
2.第二次题目集
第二次作业在第一次的基础上进行了扩展,增加了试卷和答卷的概念。试卷中包含了题目的序号和分值,并且可能存在多道题目,这导致了一种新情况的出现:答案可能并不完整,即试卷中的某些题目可能没有被作答。 在输出方面,第二次作业的要求也更为复杂。除了需要处理试卷满分不是100分的情况外,还需要考虑答卷中缺失部分答案以及处理无效的试卷号等情形。 在输入格式上,虽然与第一次作业相同,但由于作业要求的变化,正则表达式的应用也不仅仅是为了简单地将输入字符串分割成几部分,而是需要更精准地匹配和提取所需的信息。 尽管本次作业使用了类来进行封装,但在类的设计和使用上并没有完全遵循面向对象的原则,如单一职责原则、开闭原则和迪米特法则。很多判定过程仍然直接写在主方法中,没有作为类的方法封装起来,也没有使用代理类来简化逻辑。
sourcemonitor中的报表
PowerDesigner中的类图
3.第三次题目集
第三次作业是我认为的提升最大的题目,引入了删除题目和学生信息的操作,这使得输出部分需要处理更多复杂的场景,如找不到学生信息、题目被删除以及引用不存在的题目等。在这次作业中,我积极改进了代码,努力降低其复杂度,并开始有意识地遵循单一职责原则。但是因为第三次作业的难度较大,所以未能得到满分。
sourcemonitor中的报表
PowerDesigner中的类图
采坑心得:
-
第一次题目集
第一次作业虽然难度不高,但我在实践中却犯了一个重要的错误:忽视了类的封装性。它能够有效隐藏对象的内部状态和实现细节,提高代码的安全性和可维护性。由于我的疏忽,导致类的安全性大大降低,这为我后续的学习敲响了警钟。 -
第二次题目集
第一次作业我只使用了split来切割字符串,到第二次作业的输入变的更加复杂后,识别的难度也加大了,在不使用正则表达式的情况下,程序的复杂度大大提升。在题目内容迭代后,短板愈来愈明显。
点击查看代码
String str=scanner.nextLine();
while(!str.equals("end"))
{
if(str.indexOf("#N")!=-1)
{
String strs[]=str.split(" #");
String strs1[]=strs[0].split(":");
strs1[1]=strs1[1].replaceAll(" ","");
int i=Integer.parseInt(strs1[1]);
String strs2[]=strs[1].split(":");
strs2[1]=strs2[1].trim();
String strs3[]=strs[2].split(":");
strs3[1]=strs3[1].replaceAll(" ","");
Question question=new Question(i,strs2[1],strs3[1]);
listQuestion.add(question);
}
if(str.indexOf("#T")!=-1)
{
String strs[]=str.split(" ");
String strs1[]=strs[0].split(":");
int questionnum[]=new int [strs.length];
int score[]=new int [strs.length];
int i=Integer.parseInt(strs1[1]);
for(int j=1;j<strs.length;j++)
{
String strs2[]=strs[j].split("-");
questionnum[j]=Integer.parseInt(strs2[0]);
score[j]=Integer.parseInt(strs2[1]);
}
Paper paper=new Paper(i,questionnum,score,listQuestion);
listPaper.add(paper);
}
if(str.indexOf("#S")!=-1)
{
ArrayList<Answer> listAnswer = new ArrayList<>();
String strs[]=str.split(" #");
String strs1[]=strs[0].split(":");
strs1[1]=strs1[1].replaceAll(" ","");
int i=Integer.parseInt(strs1[1]);
for(int j=1;j<strs.length;j++)
{
String strs2[]=strs[j].split(":");
Answer answer=new Answer(strs2[1]);
listAnswer.add(answer);
}
AnswerPaper answerPaper=new AnswerPaper(i,listAnswer);
listAnswerPaper.add(answerPaper);
}
str=scanner.nextLine();
}
- 第三次题目集
我对学号和姓名、题目内容和题号都只是简单的将其存储在数组中,所以在输出时要多用一个循环,增加了复杂度。可以考虑使用字典HashMap来存储题目信息,以便快速根据题目编号查找对应的题目内容和标准答案。
还有一点,我在main函数中的代码过于冗余,我将错误判断和结果输出都写在main函数中,将面向对象的思想弱化了。
点击查看代码
for(AnswerPaper r : listAnswerPaper)
{
flag=1;
for (Paper p:listPaper)
{
if(r.getNum()==p.getNum())
{
flag=0;
for(int i = 0; i < p.getList().size(); i++)
{
int flag1=0;
Question w=p.getList().get(i);
for(Answer x:r.getList()){
if(x.getNum()==i+1){
flag1=1;
if(!w.getExist1()){
x.setGrade(0);
System.out.println("the question "+w.getNum()+" invalid~0");
}
else{
if(w.getExist()){
System.out.print(w.getContent()+"~"+x.getAnswer()+"~");
if(w.getStandard_Answer().equals(x.getAnswer()))
{
System.out.println("true");
x.setGrade(p.getScore(i));
r.setSum(p.getScore(i));
}
else
{
System.out.println("false");
x.setGrade(0);
}
}
else{
System.out.println("non-existent question~0");
x.setGrade(0);
}
}
}
}
if(flag1==0){
System.out.println("answer is null");
}
}
int flag1=0;
for(int j = 0;j<listStudent.size();j++){
if(r.getStunum().equals(listStudent.get(j).getNum()))
{
System.out.print(r.getStunum()+" "+listStudent.get(j).getName()+": ");
for(int i = 0; i < p.getList().size(); i++)
{
if(i < r.getList().size())
{
Answer x=r.getList().get(i);
System.out.print(x.getGrade());
}
else
System.out.print("0");
if(i!=p.getList().size()-1)
System.out.print(" ");
else
System.out.print("~");
}
System.out.println(r.getSum());
flag1=1;
break;
}
}
if(flag1==0){
System.out.println(r.getStunum()+" not found");
}
}
}
}
if(flag==1)
System.out.println("The test paper number does not exist");
}
}
改进方向
根据sourcemonitor中的报表分析可得:
1.注释率:有些文件的注释率非常低,注释对于代码的可读性和可维护性至关重要。
2.复杂度:代码的复杂度过高,复杂度高的代码段往往难以理解和维护。可以通过重构复杂方法或提取公共逻辑到单独的方法或类中来降低复杂度,例如:将HashMap使用进代码中,减少输出和比较时的复杂度;还有在输入识别时,加入正则表达式。
3.重复代码:代码的重复率较高,通常可以在项目中减少重复代码。使用设计模式、重构和封装重复逻辑可以减少代码的冗余,提高代码的质量和可维护性。
改进建议:
对于这三次作业,我认为自己在设计代码结构时并未充分遵循单一职责原则。具体来说,我意识到在处理字符串分割和总分计算等任务时,代码逻辑过于集中,缺乏必要的模块化。为了改进这一点,我可以考虑将字符串分割的功能封装到一个名为SplitStr的类中,专门负责处理字符串的分割操作。这样做的好处是,当需要在其他部分或后续作业中使用相同的分割功能时,可以直接调用Split类,而无需复制粘贴或修改原有的分割代码。
同样地,对于计算总分的逻辑,我也应该将其提取到一个独立的Grade类中。这个类将负责接收试卷的分数信息,并根据一定的规则计算出总分。通过将总分计算的责任赋予Grade类,我可以确保Answer类专注于处理与答题相关的逻辑,而不需要关心分数的计算细节。在输出内容方面,我也应该考虑引入一个专门的Print类来负责格式化并输出相关信息。这样做不仅可以使输出逻辑更加清晰和统一,还可以方便地在后续作业中添加新的输出格式或样式。通过引入这些类,我可以使代码结构更加清晰和灵活。每个类都专注于完成一个特定的任务,从而降低了代码之间的耦合度,提高了可维护性和可扩展性。在未来的作业中,如果需要添加新的功能或修改现有的功能,我可以直接在相应的类中进行操作,而无需对整个代码进行大规模的重构。我还应该更加深入地学习并应用抽象类和接口的概念。通过定义抽象类和接口,我可以建立更加通用和灵活的代码框架,使得不同类型的题目或任务能够更容易地实现继承和多态。这样做不仅可以减少代码冗余,还可以提高代码的可重用性和可扩展性。
总结:
经过这三次PTA作业的训练,我对Java编程语言有了更深入的理解,特别是在单一职责原则的运用上更加得心应手。我逐渐掌握了类与类之间的交互关系,并能更好地组织代码结构。在这三次作业中,我最大的收获之一是学会了正则表达式的应用。我深刻体会到了正则表达式在字符串处理中的强大之处,并认识到它在实际编程中的重要性。因此,我计划在今后的学习中对正则表达式进行更深入的探索和实践。我也领略到了Java库中丰富的类和接口。在解决一些问题时,我发现可以利用这些库来简化代码,提高开发效率。这也使我意识到对这些库的运用还需要进一步学习和实践。通过SourceMonitor工具的帮助,我意识到了自己在编写代码时需要注意内存使用和圈复杂度。这些指标对于代码的性能和可维护性至关重要,因此在未来的工作中,我会更加注重这些方面的优化。PowerDesigner这类工具也让我更加清晰地了解了类与类之间的关系,这对于我绘制类图和进行面向对象设计非常有帮助。这三次作业也让我对哈希表和ArrayList等数据结构有了更深入的了解。我认识到它们各自的优势和适用场景,能够在编写代码时根据需求进行选择。不过,我也意识到自己对哈希表的理解还不够深刻,需要在后续的学习中加强这方面的知识。回顾这三次作业,我意识到自己在哈希表应用方面还有待提高。同时,我也发现在处理试卷号和学生匹配等问题时,我的类设计可能存在一些不足。因此,在未来的编程实践中,我将进一步优化类之间的关系,提高代码的健壮性和可维护性。这三次作业让我收获颇丰,不仅加深了我对Java编程的理解,还让我认识到了自己在面向对象设计方面的不足。我会继续努力,不断提升自己的编程能力和设计水平。还有一点.pta平台的测试点描述太抽象了,经常不知道哪里错了,也无法下手修改。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~