0.前言:
本次博客是主要针对在java学习所有阶段中的PTA作业的总结性博客,在我看来,在本学期java学习的三个阶段中,相对于上个学期的C语言学习,各阶段的难度的跨度较大。而在第三阶段的PTA中,对java数据点的考察集中于集合类的运用、以及栈的学习和使用等。
1.作业过程总结:
(1)总结PTA所有作业之间的知识迭代关系:
第一次作业:涉及到的主要是对java语法的认识,顺序结构、循环结构、选择结构与C语言并无太大区别。
第二次作业:涉及到对java工具包中所包含的一些方法的认识和使用,与C相比所能使用的方法更丰富,以及对数组的使用,java中的数组是一种对象,在声明时需要借助关键词new。
第三次作业:涉及到对类的编写,类可以说是C语言中结构体的升级版,其中不但包括成员属性,也包括成员方法。
第五次作业:考察了对正则表达式的运用,正则表达式就是用于检索符合某个模式的文本,而这个模式则是由你编写的字符串编译而来。类的继承,子类继承自父类后,通过方法重写,拥有只属于自己的方法,通过super关键字,调用父类的方法和属性。
第六次作业:考察类的继承与多态,不同子类继承自同一父类,并且重写同一方法,将不同的子类对象赋予父类,父类可以调用不同子类对象的同一方法产生不同的结果,实现多态。
第七次作业:涉及到类对接口的实现,接口的关键字是interface,接口中的方法与抽象类相似,但接口中的方法都没有实现,类只能继承一个类,但可以实现多个接口。
第九次作业:雨刷程序功能扩展设计,这道题的解题报告中提到必须运用类的封装、继承、多态,抽象类,接口。在我看来,主要考察的是对简单设计模式的使用。我在这题中用到了集合类中的Map,也就是映射,不同的档位数字映射不同的速度,因为题目是根据输入的第一个数字的不同确定不同的雨刷系统,根据这个原因,可以构建不同的Map集合,实现不同的雨刷系统,如果需要扩展新的雨刷系统,只需要添加新的Map集合,不会对已有代码产生影响,雨刷系统的操作方法基本一致,只需要构建一个处理雨刷系统操作方法的函数即可。
第十次作业:统计Java程序中关键词的出现次数,这道题的解题报告中提到必须使用List、Set或Map中一种或多种。我在这道题的编写中,对集合类的使用仅限于利用Map类对关键词进行计数。最关键的地方在于对输入代码的操作:先将代码输入,再利用split方法分成多行数据,对每行数据的各种字符替换成空格,再利用split方法将每行数据分解成单个关键字,最后对关键字进行计数,这是我写这道题的思路。但是还要考虑到两种注释、输入代码中的字符串不计等,但这道题远比想的做法要复杂,对注释、字符串的处理需要利用正则表达式进行判定,将输入代码中字符串和注释删去后进行后续操作。在替换代码时除了想到利用replace方法进行替换外,还需要考虑输入代码中可能会出现的特殊字符等,在对Map类对象添加元素时有一个专用的方法,需要将53个关键词一次加入到声明的Map类对象中。
第十一次作业:表达式求值,这道题的解题报告中写利用栈解题。但是在java课程学习中并没有太多的提到栈的有关概念及其用法,所以这道题更多的考察的是同学的自学能力和应用能力。当然只了解作为数据结构的栈想写出这道题还是不够的,还需要学习中缀表达式和后缀表达式,前缀表达式还在理解的范围之内,但是中缀表达式转后缀表达式的理解就需要时间了,所以这道题的基本思路是,将所输入的表达式转化成中缀表达式,再将中缀表达式转化成后缀表达式,再对后缀表达式进行求值计算,利用名为栈的数据结构对中缀和后缀表达式进行存储。但是,有一半的测试点是对表达式是否合法的检验,所以在编写程序的同时还需要同时考虑,若是输入的表达式非法该如何处理。
(2)如何通过作业逐步学习java各种知识:先通过第一次作业使我们了解java语言的基本语法结构。而通过第二次作业,认识了java中部分方法的使用,构造类中的方法。在第三次作业中,我们需要自己定义类,以及通过UML图了解类与类之间的关系。在第五次作业中,初步学习到了正则表达式的运用、类的继承。第六次作业加强了对正则表达式的使用,并且在继承的基础上引出多态。在第七次作业中,是对集合类的使用以及对泛型概念的初步了解。在第九次作业中应用简单设计模式,根据问题选择合适的设计模式是非常重要的。在第十次作业中,加深对正则表达式和集合类的理解和使用。在第十一次作业中,主要考察同学的自学能力,引出对数据结构的学习。
(3)作业过程中遇到的问题及解决方法:
第一次作业:
问题:第四题判断三角形类型中第十四个测试点总是无法通过(精度问题)
解决方法:通过询问同学我发现这个测试点考察的是有理数的精度问题,的确在我考虑的范围外,修改为Math.abs(min*min+mid*mid-max*max)<0.000001解决问题。
第二次作业:
问题:求一元二次方程中,指定输出格式
解决方法:经过网上查询资料,我认识了java中的DemcimalFormat类,通过DecimalFormat df = new DecimalFormat("0.0000");声明该类对象并指定格式,再使用df.format()方法,参数是需要格式的数据,解决问题。
第三次作业:
问题:测试点下n天:整型数最大值测试,对于该测试点不知道该如何处理
解决方法:天数处理前添加for循环先将n天缩小至一年的范围,再进行后续天数增加或天数减少的操作,解决问题。
第五次作业:
1)问题:如何将输入的每行字符串储存在一起,并进行后续操作?
解决方法:先利用Scanner类读取一行,再添加到StringBuilder类的对象中,但是所有数据读进去以后,都是一行到底,也就是说与输入格式不符,后想到可以在添加时加一个换行符解决问题,即sb.append(s + "\n");
2)问题:测试点多条正确数据和测试点每一列均有误通过不了
解决方法:考察了日期的正则表达式的编写,在csdn上看到了有关博客,才解决问题,期间还重写了两次代码,但是,还有最后一个测试点多条正确数据过不去,同学告诉我说不但要用String类的trim()方法删去两边的空格,也要无视中间的空格,在其中一个根据“\t”分割字符串的操作中略微修改即可。
第六次作业:
1)问题:编写程序时没有给父类对象赋予子类对象,所以在遍历对象数组时不知道如何实现多态
解决方法:经过设置断点进行程序运行发现问题,将子类对象赋予父类对象即可。
2)问题:在对ArrayList的使用出现问题
解决方法:因为我认为ArrayList可以容纳任何不同类型的对象,于是在声明时这样写:private ArrayList list = new ArrayList();发现这种写法不通过,仔细看题目所给类图发现正确的写法应该是private ArrayList list = new ArrayList();该list列表的元素全是Term对象引用,再利用for循环和list.size进行遍历,从而使用相同父类,不同子类的方法。
第十次作业:
1)问题:对题中所提到的忽略两种注释和字符串无法进行
解决方法:对于//的注释,可对每行数据利用模式Pattern p = Pattern.compile("//.*");进行匹配,对于字符串利用模式p = Pattern.compile("\"([^\"]*)\"");进行匹配,若匹配到了,则删除或忽略该部分;对于/*....*/的注释,在输入每行代码时利用Pattern p = Pattern.compile(".*/\\*.*");进行匹配,若匹配,不对该行代码处理,直至遇到p = Pattern.compile(".*\\*/");匹配的语句,再对该段语句删除或忽略。
2)问题: 测试点2:[]以及,分隔 和 测试点3:;分隔 未通过:
解决方法:没有考虑到这几种符号,利用date = date.replace(","," ");等语句可解决问题。
3)问题:测试点9:正常测试 未通过
解决方法:至今未解决,这是我所有作业中唯一没有通过的测试点;
第十一次作业:
1)问题:测试点10:含有0开头数据 未通过
解决方法:因为在普通表达式转化为中缀表达式的过程中,会对多位数进行转化,即遇到数字时,会对后一位进行判定,若后一位也是数字,与前一位连接,直至后一位是非数字,但是在判定的时候忽视了0开头的数据也是合法的,对判定条件进行修改后解决问题。代码如下:
第十一次作业
2)问题:在中缀表达式转化为后缀表达式时出现问题,部分表达式符号消失
解决方法:发现在转换过程中,对符号优先级的判定出现问题,修改成下列代码解决问题:
if(CompareOper(ele)>CompareOper(s1.peek())){//ele是进行比较的元素
s1.push(ele);//s1是储存符号栈
}else{while(!s1.isEmpty()&&(CompareOper(ele)<=CompareOper(s1.peek()))&&!s1.peek().equals("(")) {
s2.add(s1.pop());//s2是储存中间结果的链表
}s1.push(ele);
}public int CompareOper(String oper) {//对入栈前的运算符优先级进行比较
if(oper.equals("(")||oper.equals(")"))return -1;else if(oper.equals("*")||oper.equals("/"))return 1;else if(oper.equals("+")||oper.equals("-"))return 0;else{
System.out.println("Wrong Format");
System.exit(0);return -1;
}
}
第十一次作业
(4)每次作业花费的时间比例:
第一次作业时间:第二次作业时间:第三次作业时间=1:3:6;
第五次作业时间:第六次作业时间:第七次作业时间=4:3:3;
第九次作业时间:第十次作业时间:第十一次作业时间=1:4:5;
(5)对编程过程的严谨性的认识及教训:
认识:
在JAVA的学习中,一共进行了9次PTA作业,其实对程序的编写过程的时间并不长,主要的时间还是花费在如何编写程序以及如何将编写的程序修改至无误上,仅仅知道所需要编写的程序是应该用什么算法如何编写是不够的,因为所编写的程序的运行结果往往不如你所愿,所以就需要跟着程序一步步运行,寻找出错的代码,然而这个过程往往是不容易的,甚至可以说是非常辛苦。所以,在编写程序时保持严谨性就显得尤其重要,能减少一些不必要的错误,不能一味依靠eclipse,因为有些错误是它所不能检测出来的,比如if语句括号后的分号,会导致if语句内容不会允许,并且寻找起来时间。
教训:
在完成作业的过程中确实得到不少缺乏严谨性的教训,比如,在第十一次作业中,中缀表达式转化为后缀表达式,仅仅是因为对运算符号的比较级的环节出问题,我就花了近五个小时来寻找错误,还认为是测试点中有对负数的处理是自己并未考虑到的,若不是同学的提醒,这道题或许我还不能完成,还有数组越界的问题,由于C语言中并没有数组越界检查,在编写java程序时多次出现数组越界错误后,才意识到自己对于数组的操作是非常马虎的。所以,我应该在今后的学习中,需要认真且严谨,程序只会因为我的不严谨产生错误,而不是顺利运行。
2.OO设计心得
(1)对面向对象三大技术特性之间关系的理解:
封装性保证了类内部成员的密封性,外界程序不能轻易修改类内部数据,提高了程序的安全性和可靠性,合理选择类、方法、属性前的修饰词也很重要;继承是类与类之间的一种十分重要的关系,有了继承,程序员可以减少编写代码的量,类与类之间的关系也更加灵活,java语言有了继承性,才能实现多态;而子类对抽象类的继承、对接口的实现从而产生了多态性,子类对象是父类对象的实例,为相同的父类对象赋予不同的子类对象,通过父类的引用访问继承层次中不同子类对象的相同方法。
(2)面向对象设计的基本原则理解:
1)单一职责原则:单一职责原则核心思想是一个类,最好就做一件事。
2)“开-闭”原则:“开-闭”原则的核心思想是软件应该是可拓展的,不可修改的,若只对代码进行拓展,出现错误,只需要在拓展部分寻找错误即可。
3)依赖倒转原则:高层模块不应该依赖底层模块。
4)里氏代换原则:利用多态特性,父类作用的地方可以使用其任意子类替代。
5)迪米特法则: 一个对象应当对其它对象有尽可能少的了解。
(3)OO编程思维的理解:
oo设计主要是面对对象,面对问题时,不同于面对过程是针对解决问题一步步解决,oo设计首先需要找到问题中所涉及到对象,每个对象都有自己能做的事情和不能做的事情,再根据所寻找的对象定义类,探究类的共同点,利用抽象类和接口实现类之间的联系,根据问题选择合适的设计模式,合理设计类间关系,也要注意不能定义过多的类,造成类的泛滥。
3.测试的理解与实践:
①测试对于编码质量的重要性
测试对于编码质量是非常重要的,即使我们还处于完成作业的阶段,我们也应该对自己所编写的代码持有高度的严谨性,通过设置测试点我们可以知道所设计程序中的不足,了解自己所没有考虑到的方面,以及程序中隐藏的错误。如果没有测试,你甚至都不知道自己程序是否是否能够正常运行至最后。
②假如让我设计测试用例
注意对测试点的选择,选择普通测试点的同时也要设置边界测试点,也需要设置对程序主要函数的检测,设置的测试点越多,通过的测试点越多,说明所编写的程序完成度越高。
4.课程收获:
收获:
1.通过这次java课程的学习,自己的收获还是很多的,首先就是对java知识的学习,在第一阶段中,了解了java最重要最基本的两个元素——类和对象,在第二阶段中,学习到java的三个特性——封装性、继承性、多态性,也认识了许多已有的类,比如集合类等,还有困扰我很久的正则表达式,在第三阶段中,学习了一些设计模式等。
2.课程中为了完成作业重写了很多次代码,完成作业固然重要,比如在第十一次作业中输出一个“wrong format”就能拿到50分,但是更重要的是如何通过作业应用课程中学到的诸多知识,只依靠老师上课时所教导的知识是远远不够的,在编写程序时遇到问题不能一味发呆浪费时间,要积极去网上寻找资料或者询问同学,老师上课所传授的只是一部分内容,而更多的内容需要我们在课后自己去查询和学习。
3.JAVA和C的区别是很大的,不能以C的思想去写JAVA程序,学习JAVA并不是看老师写代码就能学会的,当然多看代码也是很重要的,需要在学习某个知识点后,自己使用自己的IDE工具自己编写一遍,才会有更深的理解,否则在写作业时,你会觉得这个知识点我学过,但是该怎么编写呢?这是我的亲生体会。
4.需要对设计的基本原则有自己的理解,基本原则的介绍每个字都认识,可是在编写代码时要将其实践确不是一件容易的事情。还有诸多设计模式的应用,根据问题选择合适的设计模式,合理的设计类与类之间的关系。
5.学习向来不是一件轻松的事情,并不是一时努力一时懒惰就会有美好的未来。想要学好JAVA,代码量是必须的,勤奋也是必须的,无论什么时候都不能放弃学习。
教训:
教训还是挺多的,首先,不要自以为是地认为老师教的东西自己通过自学就能学会,就算上课的时候听不懂,也要把自己听不懂的地方记录下来,课后去查找资料,不能随便就不听了;其次,不要天真地以为这次作业通过了自己就很好地掌握了这次作业所考察的知识,因为作业考察的只是一部分,别养成把作业留到最后几天完成的习惯,因为你根本知道作业考察的内容你是否掌握。
5.对课程的建议:
1.希望老师上课讲解的时候能稍微慢一点,有时候低头记了一下笔记就不知道老师在讲哪里了。
2.还有就是希望老师有时间可以讲解一下PTA上的作业,或者在PTA作业结束后把一些很少人通过的测试点给我们,可以加深同学对知识点的理解与使用,比如在第十次作业的测试点9,测试点的提示是正常测试,所以我实在不知道该如何对程序改进。
3.我觉得老师教得还是很不错的,我也是在听了老师的课以后才能顺利完成绝大多数作业。