Java第二次总结
Java第二次总结
一、前言
1.从第四次题目集开始,虽然题目数量减少,仅仅只有三题,但是题目难度相较于之前的题目集整体难度略有提升,对于有些题目来说,题目难度更是加大了许多,对我来说有一定的难度,很有挑战性,例如第四题目集的水文数据检验及处理。这次题目集主要引导我们开始慢慢创建并使用类与对象,处理类与对象间的关系。
2.第五次题目集题目开始变多,但是多出来的题目却很简单,感觉只是单单磨练我们的基础算法知识,加深我们的基础语法。只是第四题统计Java关键字那题很让人难受,与几位同学一起讨论过,处理这题花费了大量时间。这个题目集开始让我们更加清楚的认识类与对象间的关系的处理,到底我应该使用关联,聚合,还是组合,或是依赖。也明显区分了各种关系间有什么区别及使用的优缺点。
3.第六次题目集题目难度开始降低,对我来说有点简单,在我看来只是单纯的知识点训练,前几题是关于正则表达式的简单使用,让我更加熟练了正则表达式。最后两题是让我慢慢学习了继承和多态,理解了继承和多态的优缺点,也学会了初步使用。
4.总的来说,这个月的三次题目集着重点在于正则表达式的训练,类与对象的使用及关系处理,继承和多态,父类与接口的初步使用。难度偏易,代码行数大幅增多。
二、设计与分析
1.日期聚合类设计优劣比较
(1):题目集四(7-2):该题为我们第一次根据类图写程序,类图如下:
该题目是以聚合的形式来画的类图,但最开始时候我的思维没有考虑到如何使用聚合的方式来进行代码编写,于是使用了组合的方式,类似于下图方式:
我是在一个类新建时进行的new 对象操作,这使得两个类的生存周期相同,成了组合的方式。类图中的每个箭头都是这样,于是乎这道题的解法就和老师的要求有了点不同,但是相同的是,year,month,day三个类之间存在这关系。在后来我重新思考了该题目,发现真的能使用聚合的方法,就是通过setter方法进行传入类的对象,但实际上这样去使用的话,就会使得带参数的构造方法无法使用,程序会报每个类的引用对象为空。使得所有类的成员变量只有通过setter方法进行设置。
反向生成类图后,根据类图显示,的确这四个类存在关联关系,每个类的存在都离不开上一个类,呈现于组合关系。
经过分析后,发现只有Main类 的复杂度很高,原因在于我的判断输入,使用了switch 与 if 语句的嵌套使用,加大了复杂度,这点我与同学进行了反复讨论,没有得到很好的处理办法。问题代码如下:
switch(flag) {
case 1: //计算输入日期下n天
year = sc.nextInt();
month = sc.nextInt();
day = sc.nextInt();
n = sc.nextInt();
date = new DateUtil(year, month, day);
if(!date.cheakInputValidity() || n < 0) {
System.out.println("Wrong Format");
break;
}
date = date.getNextNDays(n);
System.out.println(date.showDate());
break;
case 2: //计算输入日期的前n天
year = sc.nextInt();
month = sc.nextInt();
day = sc.nextInt();
n = sc.nextInt();
date = new DateUtil(year, month, day);
if(!date.cheakInputValidity() || n < 0) {
System.out.println("Wrong Format");
break;
}
date = date.getPreviousNDays(n);
System.out.println(date.showDate());
break;
case 3: //计算两个日期相差的天数
year = sc.nextInt();
month = sc.nextInt();
day = sc.nextInt();
date = new DateUtil(year, month, day);
int year1 = sc.nextInt(), month1 = sc.nextInt(), day1 = sc.nextInt();
DateUtil date1 = new DateUtil(year1, month1, day1);
if(!date.cheakInputValidity() || !date1.cheakInputValidity()) {
System.out.println("Wrong Format");
break;
}
n = date.getDaysofDates(date1);
System.out.println(n);
break;
default:
System.out.println("Wrong Format");
break;
}
(2)题目集五(7-5):这次为我们第二次重新接触日期类聚合设计题目,这次的题目类图有所改变:
这次有关日期的三个类分开来了,year,month,day这三个实体类之间没有了直接关系,而是使用了中介类来使他们产生联系,所有的处理都来放在了DateUtil 这个中介类中,类与类间的关系变得更加简洁明了。根据类图,我当时考虑的设计沿用了上个题目集日期处理的想法,使用了组合关系,DateUtil 类与三个实体类之间为组合关系,即我是在dateUtil类的构造方法中分别new了三个实体类的对象,这样三个实体类没有任何关系,大大降低了类与类之间的耦合性,提高了程序的维护性。
但是由于我是用的为组合关系,同上个题目集一样,老师要求最好为聚合关系,所以我也考虑了重新使用聚合关系来修改我的程序,即在main类中new三个实体类的对象,在通过setter方法进行出入,但是这样,图中给的带参数构造方法就没法使用了,所以我猜测老师主要考察于我们三个实体类间 的聚合关系,而不是和中介类的关系(仅限于个人理解)。
反向生成类图:
根据类图,说明了三个实体类间确实没有任何关联关系,DateUtil类与三个实体类间具有关联关系,基本符合题目要求。
通过分析复杂度图:
由于实体类间的关系及部分处理方法变得简单,所以实体类的复杂度有所下降,但是主类复杂度依旧很高,原因还是很上个题目集一样,由于使用了switch 与 if 语句的嵌套,复杂度很高,这点需要我去改进。
(3)两次题目使用类关系比较:
第一次题目集使用的为实体类与实体类,实体类与中介类都为组合的关系的方式,这样的优点在于环环相扣,申请一个处理对象后,每个实体类都会立即生成一个对象,一个实体类对象改变会引起另一个实体类对象的改变,例如:当天数加一时,day对象改变可能会直接去改变month对象。但是缺点也很明确,因为使用了组合,类与类之间的耦合性很高,难维护,难修改。
第二次题目集就将实体类分开了,实体类与实体类之间没有了直接关系,这样的优点很明显就是耦合性大大降低,维护变得简单。还有就是实体类的复杂度也得到了降低,程序变得更加简洁明了。
2.继承设计的思路与技术运用(封装、继承、多态、接口等)
本月的三次题目集还让我们接触并学会使用了封装、继承、多态、接口;类的封装早在上个月的程序中已经有所体现,但是继承,多态与接口则是这个月的新知识,也是重点之一。
(1)题目集四(7-3):该题要求我们定义一个父类shape,其中有一个计算面积的公有方法,其他有四个实体类:Circle,Rectangle,Ball,Box,Circle与Rectangle都继承于类shape,获得计算面积的方法并Override。另外,Ball 和 Box类分别继承于Circle与Rectangle,还拥有两个属于自己的共有方法用于计算体积。这道题目是我们初次接触了类的继承与多态性的使用。当时只是知道具体语法的实现,并不知道使用继承设计思路的优点是什么。但是经过题目的诱导测试,发现子类在调用构造方法时,会先调用父类的构造方法,例如:当我调用Circle的构造方法时,他会先调用Shape的构造方法; 如果我调用Ball 的构造方法时,他又会先调用Circle的,而Circle又会去调用Shape的。
程序运行如下:
首个输入的4表示调用类Box对象,后面则表示输入图形的各个参数,计算面积和体积,可已看出,他调用了父类的构造方法。
分析其类图:
类图很好的说明了各个类之间的继承关系。Box与Ball继承于Rectangle和Circle,后两个都继承于Shape。他们间有很强的关系。
分析其复杂度图表:
复杂度只有主函数很高,原因还是很前面题目相同,都是为了判错而使用了判断语句嵌套的问题,这一点真的值得我去思考如何解决。
(2)题目集六(7-5):这次题目是上次题目的加强版,还是有关继承和多态的问题;要求我们创建一个抽象类Shape,其中包含有三个抽象方法,用于计算面积,输入数据检查与返回输出字符串。这道题目不仅仅要求我们使用继承,还让我们学习了使用多态,及每个子类Override 抽象方法,使之适用于自身。在进行程序编写时,应老师要求,我们使用了list 链表数组,使用了Shape泛化,构建了一个可以容纳Shape类的链表,因为父类的引用可以储存子类的对象,所以这个链表能很好的储存我们输入的数据,然后通过覆写的方法计算了每个对象的面积,完成了题目要求。
对于这题,我第一次接触了抽象类和多态的使用,加深了对于链表与泛化的使用,更加明白了关于继承在使用时父类与子类间的部分关系,对于抽象类,不能直接new。
对于类图分析:
Circle ,Rectangle, Triangle类都继承于Shape类。
对复杂度分析:
复杂度都在10以内,符合要求,这次的判断没有题目可以不适用判断语句嵌套,所以复杂度没有那么高,Shape为抽象类,在程序运行时无实际作用,所以复杂度为0;
(3)题目集六(7-6):该题目不再是继承父类,而是接口了,这是我第一次使用接口,学会了接口的基本语法,了解了接口与父类间的关系与区别,老师给的题目类图如下:
按照老师的类图,编写完代码进行分析;接口中的方法全是public abstract 类型的,根据题目,发现接口的引用可以存放引用接口的对象。这道题目只是单纯的要求我们学习接口的使用,没有太大难度。
类图分析:
Rectangle 与Circle类拥有GetArea接口。
关于复杂度问题,我真的全是使用了判断语句嵌套导致的复杂度过高。
3.正则表达式题目分析
正则表达式也是这个月的重点之一,正则表达式是我这学期学到过最有用的东西之一,可以很大程度上帮助我们判断复杂的输入,还可以进行提取,替换,删除操作,对于大部分要求检查输入的程序都可以胜任。我们这个月从第四次题目集到第六次题目集,每次都有至少一题是有关正则表达式的,充分锻炼了我们正则表达式的运用。 其中较难的是第四次题目集中的水文数和第五次题目集的java关键字统计。
判断水文数时,主要先使用正则表达式将水文数分成六个部分,在依次判断每部分是否正确,在判断这道题目时,有两个测试点很难通过,经过认真查看后发现,是正则表达式错误,误判了一种情况,最后修改后通过该题目。所以在我看来,使用正则表达式需要很严谨的思维,否则正则表达式可能匹配的情况过多或者一些特殊情况无法匹配。
在统计关键字时,就是先将不符合题目要求的部分删去,最后通过正则表达式的字符查找与匹配,统计关键字。这道题目难在最后一个测试点,无论这样我们都没法通过。最后通过大量时间验证,发现最后一个测试点在忽略点删去注释的操作后(既保留注释),可以通过,但同时有注释的测试点就会报错,多名同学讨论后,认为是题目问题。我在后来测试中突发奇想,认为题目存在部分漏洞,即该题目的每个测试点代码行数完全不一样,我可以通过限定代码行数从而限定是否删去注释,这样操作可以同时通过两个测试点,即题目正确。这样虽然通过了题目,但是属于剑走偏锋,希望不要采取这样的方法。
第六次题目集给了很多小题目进行正则表达式的训练,对于我来说题目过于简单,没有任何问题。
通过三次对正则表达式的训练及先前的练习,已经能完整运用正则表达式解决问题,提升很大。
4.Java集合框架应用的分析总结
题目集五(7-4)统计Java关键字题目要求我们使用set,list,map中的一种,在这些中,我最熟悉的是list,其次为map,set我不清楚是什么,但是通过后面的查阅资料,学会了三种集合框架的基本语法,该题目我是使用list来解决的。
如下图:
该题目我使用了StringBuilder进行输入储存,使用了泛化为String的ArrayList进行输出存储。
虽然使用很少,但是使用语法基本学会,并总结了几个使用的特点:
第一点:使用时可以不用管长度问题,相当于C语言中的指针,可以动态开辟空间,不用事先知道输入长度。
第二点:储存在其中的元素无法得到修改,否则list会报错。
第三点:需要使用遍历输出或使用get方法得到元素。
第四点:效率较高但是在特定位置增加删减元素很麻烦。
该题目复杂度为:
复杂度都不是很高,原因在于该题使用的是正则表达式进行判断与匹配,效率高,复杂度低。说明正则表达式比if语句效率要高得多。
三、踩坑心得
1.正则表达式:正则表达式中的 \ 转义符也需要转义后才能作为转义符,即 \\ 表示一个 \ ,如果需要匹配 \ ,则需要四个 \ 。
2.list链表无法遍历时修改:我曾在在list表遍历时去修改,程序不报错但是程序运行不了,最后发现错误,重新定义新的list表存储修改后的list表。
3.需要注意引用变量传入方法中是会被修改的,如果不想它被修改,需要建立一个新变量出入方法中。
四、改进建议
1.题目集五(7-4):该题目我使用的为list链表,但是我后来学习了HashMap 表后,我觉得使用HashMap会更好,在我使用list时,是将Java关键字的数量转换为string类型于关键字一起组成一句字符串存入list中,而使用HashMap则可以分开存储,数字和关键字分开作为整体存入。这样改进我觉得可能更好。
2.日期类题目集:我觉得真的可以根据老师画的类图来修改,将自己的组合方式改为聚合方式,通过setter方法传入对象,这样虽然带参数构造方法无法使用,但是并不会影响程序结构。
3.这些题目中最应该改变的为我的输入判断,都是同一个原因(语句嵌套)导致复杂度过高,我不知道是程序结构问题还是有更好的判断方法,我会慢慢改进。
五、总结
1.基础知识方面:本月学习了三大知识点,分别为:类与类间的关系,程序设计中的继承思想(抽象类,接口的使用及多态性的运用)、正则表达式的复习与加深。复习了基础语法和算法知识,在基础语法方面已经没有了问题。
2.需要深入学习的方面:主要在于类与类之间的关系的设计及继承设计的运用,虽然已经了解了部分知识点,懂得了基础语法,但是在运用于程序设计上还差距过大,需要大量的练习及积累进而提升自己的水平。在正则表达式方面也有需要加深的地方,例如:在设计正则表达式时,需要考虑特殊情况的处理,而且正则表达式在有时也是不适用的,需要单独判定。这些知识点都需要大量的积累,所以在以后的学习中要多加考虑问题,提升自己的思维能力,多思考为什么,不局限于只是做对题目。
其中,最应该学习的是对于程序复杂度的简化、对于方法的合理使用。这几道题目都是应为判断输入错误使用了判断语句嵌套而导致复杂度过高,这个地方下个月我会想办法解决。
3.本月学习中学到很多很好的查找错误的方法,如:断点,单步,看数据的变化等等。
4.个人建议:我觉得现阶段的题目对于我个人而言还是处于适中阶段,希望老师看能不能根据个人情况单独布置一道较难题目,时间可以是很长的那种,可以让我自己去查资料,自己学习很长时间,能让我更多的去思考。