第二阶段作业总结报告
一、前言
(1)实验感受
第二阶段的作业总的来说题目难度由大到小,题目数量由少到多。也开始正式的接触到了面向对象程序设计的核心内容:图形的继承和多态等加上接口的应用。通过作业逐步理解了面向对象的封装性、继承性、多态性三大技术特性。题目的要求也变得越来越严格。
对于初学者来说,学习这些特性还是有一定难度的,所以遵守规则,完成题目要求,循序渐进就能掌握这些知识。
(2)题目集分析
第四次题目集:实验分为三道题。
1、考察String Builder对输入数据的接收处理。
2、考察类与类之间的依赖、聚合、继承关系。
3、考察正则表达式的使用。
4、考察字符串的查找和删除。
5、考察字符型数据与数值型数据之间的转换。
6、考察LocalDate的使用。
难度总结:7-1难度较大,其余两题难度适中。
第五次题目集:实验分为五道题。
1、考察字符串查找、排序、删除;
2、考察数组排序合并数组元素;
3、考察List相关方法的使用;
4、考察三种排序法(插入排序、选择排序、冒泡排序)使用;
5、考察类与类之间的聚合关系;
6、考察考察String Builder对输入数据的接收处理;
7、考察正则表达式的运用;
8、考察List、Set或Map接口的使用;
难度总结:7-4题目难度较大,其余题目难度适中。
第六次题目集:实验分为六道题。
1、考察正则表达式的运用;
2、考察字符串排序;
3、考察图形接口;
4、考察图形继承与多态;
5、ArrayList常用方法及和数组的关系;
6、泛型的应用;
7、Arrays及Collections的简单应用;
难度总结:难度适中。
二、设计与分析
①关于题目集4(7-2)、题目集5(7-5)两种日期类聚合设计的优劣比较
首先我们应该知道聚合是什么:它是两个类之间的关系,是一种HAS-A关系,是一种单向关联。如果类具有实体引用,则称为聚合。
通常在定义一个整体类后,再去分析这个整体类的组成结构,从而找出一些成员类,该整体类和成员类之间就形成了聚合关系。
在聚合关系中,成员类是整体类的一部分,即成员对象是整体对象的一部分,但是成员对象可以脱离整体对象独立存在。
对于题目集四7-2
聚合方式为:DateUtil()类包括Day()类,Day()类包括Month()类,Month()类又包括着Year()类。
类图如下所示:

从图中我们可以看出,它们之间调用是层层调用。
圈复杂度如下:

对于题目集五7-5
聚合方式为:DateUtil()类包括Day()类、Month()类、Year()类,即DateUtil()类由Day()类、Month()类、Year()类组成。
类图如下所示:

由图可以看出:该聚合关系是由一个主要类分别调用其他类。类之间关联性不是很强。
圈复杂度如下图所示:

(1)从复杂度角度:由圈复杂度可以看出两种聚合方式复杂程度第一种聚合方式简单一点但是其实差不多少。
(2)从耦合度角度:对模块间关联程度来看。第一种聚合方式模块间接口的复杂性程度比第二种聚合方式高、调用模块的方式更复杂以及通过界面传送数据更麻烦。模块间的控制关系、调用关系、数据传递关系更繁琐。后面的Day()类、Month()类、Year()类独立性差。我们知道对象之间的耦合越高,维护成本越高。因此对象的设计应使类和构件之间的耦合最小。所以第二种聚合方式要优于第一种。
(3)从整体角度:对于代码的修改,由于第一种聚合方式是每个类先后关联,所以修改起来需要全面修改很麻烦。然而第二种聚合方式每个类之间关联性不是很强,易修改。在第二种聚合方式情况下,一旦哪个类出现问题,能快速的寻找到根源,并且不会影响到其他类中的方法。
②题目集4(7-3)、题目集6(7-5、7-6)三种渐进式图形继承设计的思路与技术运用(封装、继承、多态、接口等)
(1)对于题目集4(7-3):类图如下

由类图可以看出:
考察的主要是对象的创建、父类的继承、方法的重载、基本输入等等。例如set()方法设置属性,this关键字的使用(区分同名的实例变量和局部变量如:this.name = name);get()获取属性,return返回值。继承extends,方法的重载,super关键字(调用父类的方法和属性如:super.getArea())。super调用的是父类的构造函数,super关键字必须在子类构造方法的前面。

由复杂程度报表可以看出复杂程度适中。
此次题目是简单的图形继承,类Shape,无属性;类Circle,继承自Shape;类Rectangle,继承自Shape;类Ball,继承自Circle;类Box,继承自Rectangle。父类Shape中含有公告方法public double getArea();//求图形面积,这样两个子类Circle和Rectangle就能重写父类中求面积的方法进行调用。求体积时也是一样。
(2)对于题目集6(7-5):类图如下

由类图可以看出:
子类Circle继承父类Shape,子类Rectangle继承父类Shape,子类Triangle继承父类Shape。
这里考察的不仅是对象的创建、父类的继承、方法的重载、基本输入等等,相比较于题目集4(7-3)除了set()方法和this等关键词的使用外,还增加了多态的应用。如下图:

多态是继封装、继承之后,面向对象的第三大特性。在有子类的情况下,多态体现为父类引用变量可以指向子类对象。即类Circle、类Rectangle、类Triangle都是类Shape的父类,我们只是通过Shape这一个父类就能够引用不同的子类。Java实现多态有三个必要条件:继承、重写、向上转型。只有满足了上述三个条件,我们才能够在同一个继承结构中使用统一的逻辑实现代码处理不同的对象,从而达到执行不同的行为。
使用多态的好处是:多态对已存在代码具有可替换性。
多态对代码具有可扩充性。增加新的子类不影响已存在类的多态性、继承性,以及其他特性的运行和操作。
灵活性,它在应用中体现了灵活多样的操作,提高了使用效率。
简化性,多态简化对应用软件的代码编写和修改过程,尤其在处理大量对象的运算和操作时,这个特点尤为突出和重要。
圈复杂度如下图所示:

由于Main类和Triangle类所包含和实现的功能较多导致比其他类的复杂程度更高,但总的来说复杂程度适中。
(3)对于题目集6(7-6):类图如下:

由类图中我们可以看出:
相比较题目集6的7-5,这里多使用了接口的相关内容。而非简单的继承关系。
如下图:

这里定义了一个接口GetArea含有getArea的其面积的抽象方法。并且Circle及Rectangle分别为圆类及矩形类,分别实现GetArea接口。我们只需要在相应类中重写该方法就能实现方法的调用。调用如下图

圈复杂度如下图所示:

由此图可以看出,相比较以上两种聚合方式,复杂度明显低于前面两种聚合方式,运用接口可以使代码更为简单易修改。
对于接口的使用,我们可以理解为接口就是一个招牌,我们在里面存放多个类都将实现的方法,主要是是为了减少代码书写并且有利于代码的可维护性和扩展性。如果代码出现问题,使用接口能快速分离代码并且不会影响其他代码的使用。
总的来说接口也是一种代码的规范,也可以减少代码的耦合性,使代码变得更简单,容易修改。
图形的继承可以有多种方法,主要是对象的创建、父类的继承、方法的重载、基本输入,却有很多种方式实现该继承,每种方法都有好处和坏处,所以我们应该注重学习这些方法。
③对三次题目集中用到的正则表达式技术的分析总结
关于正则表达式,正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式可以用来检索、替换那些符合某个模式(规则)的文本;可以通过一些设定的规则来匹配一些字符串,是一个强大的字符串匹配工具。‘
Java利用反斜线(\)处理正则表达式
一些常用正则表达式如下:


使用环境:
(1)与对字符串的判断结合,如题目集6中的7-1:

在这里用到了find()方法还有Pattern和Matcher的使用。Pattern对象是正则表达式的已编译版本。它没有任何公共构造器,我们通过传递一个正则表达式参数给公共静态方法 compile 来创建一个pattern对象。Matcher是用来匹配输入字符串和创建的 pattern 对象的正则引擎对象。这个类没有任何公共构造器,我们用patten对象的matcher方法,使用输入字符串作为参数来获得一个Matcher对象。还有一种使用matches方法,通过返回的布尔值判断输入字符串是否与正则匹配。
(2)与对字符串的提取结合,如题目集5中的7-4:

在这里用到了replaceAll方法对字符串进行删除。
(3)与对字符串的分割提取结合:如题目集5中的7-4:

通过split方法对字符串进行以空格为分割点,分割成多个子字符串。
总结:使用正则表达式可以使代码的效率变高,相比较于if等判断语句代码的复杂度也明显较低。使用了这么多次正则表达式,对于常用的字符已经完全掌握。
④题目集5(7-4)中Java集合框架应用的分析总结
集合框架概念:
面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。另一方面,使用Array存储对象方面具有一些弊端,而Java 集合就像一种容器,可以动态地把多个对象的引用放入容器中。
Java集合主要有两种体系,可分为Collection和Map体系。
Collection接口:单列数据,定义了存取一组对象的方法的集合有下列两种形式:
List:元素有序、可重复的集合
Set:元素无序、不可重复的集合
具体关系如下图所示:

Map接口:双列数据,保存具有映射关系“key-value对”的集合
具体如下图所示:

1、对象封装数据,对象多了也需要存储。集合用于存储对象。
2、对象的个数确定可以使用数组,对象的个数不确定的可以用集合。因为集合是可变长度的。
在此题目中我使用接口Collection,进行数组数据储存排序

总结:Java的集合框架应用的好处
(1)使用核心集合类降低开发成本,而非实现我们自己的集合类。
(2)代码质量会得到提高。
(3)通过使用JDK附带的集合类,可以降低代码维护成本。
(4)复用性和可操作性。
三、采坑心得
1、语法错误:通常,编译器对程序进行编译的过程中,会把检测到的语法错误以提示的方式列举出来。
主要有括号不匹配,变量未声明(此类错误最多)如下图:

数据类型之间的转换。例如String输入,int or double输出时。如下图:

我认为出现此类错误是好解决的。此类错误一般程序编译系统会自动提示相应的错误地点和错误原因,比如哪一行代码少了个括号等诸如此类的提示,常见的错误,看懂直接改正即可,如果是看不懂原因,可以将错误提示信息输入搜索引擎查找一下,一般都能找到具体的解决办法。需要的是多练和细心。
2、逻辑错误:由于编译器无法检测出存在的逻辑错误,所以此类错误有点麻烦。
主要有遗漏的情况出现。例如题目集5中的7-4,容易遗漏“”中的内容也属于字符串中的数据。
还有循环条件错误,指令的次序错误,程序设计算法考虑不周全等,尤其是当题目所涉及的情况较多时容易遗漏。在一般情况下,编译器在编译程序时,不能检测到程序中的逻辑错误,也不会产生逻辑错误的提示,因此逻辑错误比较难排除,需要我们仔细的分析程序,并借助集成开发环境提供的调试工具,才能找到出错的原因,并排除错误。
3、运行错误:运行时被迫中止且编译器开始不能产生提示。
主要有数组元素超出范围。(主要报错:ArrayIndextOutOfBounds数组下标超出边界)如下图:

方法的使用前后不匹配或找不到所要的头文件,如下图:

此类错误发生时,编译平台一般也会提示相应的信息,对于常规的错误会有比较精确地提示,但有时提示的错误原因会比较模糊,但因为此类错误一般在程序运行时,只在特定的条件下才会发生,所以根据错误发生的条件,能够大致判断程序出错的代码段,结合错误的原因,也能比较方便的调试出错误。
四、改进建议
(1)对于题目集6中的7-2相关排序问题,在一般的情况下可以不用排序法进行排序,可以直接使用sort等方法进行排序,主要有Arrays和Collections。
(2)对于题目集4中的7-1中if-else语句嵌套过于复杂情况可以考虑使用相似逻辑进行判断的一般情况下可以使用switch语句进行取代,可以使得代码可读性更高。
(3)对于调用关系复杂的类可以考虑定义一个父类或者中间类来使各类之间的耦合度降低从而达到简化代码的目的。这样也可以容易修改和调整,增加代码可读行。
五、总结
1、学到了什么
首先是正则表达式,包括正则的效率问题,了解到正则表达式的巨大作用。并且通过大量正则表达式的练习,对于正则表达式的使用环境还有常用的表达式已经掌握良好。
其次是类与类之间的关系(聚合、继承、关联等),了解并掌握了这些常用方法的使用。并且发现了这些方法的有点和缺点,但比较于以前的方法,使用这些方法可以使类之间的关系更加紧密,并且调用和实现起来更为方便和检查。
学习了很多新的概念和知识,例如接口的定义和使用,使用方法(sort、split等)的学习。并且接触到了面向对象程序设计的核心内容:多态等。
最主要并且让我印象深刻的知识是多态的使用,这既是难点也是Java的重点内容。
对于进一步研究方向,我认为简化代码复杂度和学习更好的算法是接下来的学习方向。学习更优的方法。

浙公网安备 33010602011771号