OOP第一次总结

OO作业第1-3次总结

一、前言

​ 本次总结是我上OO课的第一次作业总结,上学期我们学习的C语言程序设计主要是面向过程编程,而这学期的Java则主要应用于面向对象编程。在前三次作业的学习过程中,我逐渐了解了面向对象语言的三大特性:封装、继承、多态,尤其是第二、三次作业的题目,要求我们进行一个类设计的题目,让我感到有些不适应。总之,前三次作业题量适中,难度也是逐层递进,更像是我从面向过程到面向对象的一个过渡,让我能快速进入面向对象的世界。

二、设计与分析

  1. 第一次作业

    1. 题目7-8

      ​ 本次作业要求判断三角形的类型,因为只有一个三角形,所以不用涉及面向对象的编程,直接运用面向过程的知识解决。这题正是检验我们学习java基础语法,没有太过复杂的程序设计内容。

      ​ 在进行三角形类型判断的前面,我首先考虑到输入数据的合法性,题目要求三条边的范围在[1-200]之间,所有输入的数据都是整形或浮点型,用一个if语句判断。

      ​ 在数据存储方面,我使用了一个大小为3的数组,一是为了方便使用数据,二是为了将边的长度排序,减少不必要的麻烦,方便边的判断。

      ​ 接下来判断是否能构成一个三角形,如果是三角形再根据三边关系判断三角形的类型。

      ​ 本次作业较为简单,但有很大的意义,让我对基础知识有了一定的巩固。

      Method CogC ev(G) iv(G) v(G)
      Main.main(String[]) 15 1 8 14

      ​ 根据复杂度分析,可见CogC(认知复杂度)和v(G)(圈复杂度)都比较高,应进一步优化代码。

  2. 第二次作业

    1. 题目7-4

      ​ 第二次作业是第一次作业的进阶,题目要求程序实现求任意一天的下一天,并且使用自定义的方法(其实我最先想到用Date类里面的求下一天的方法),程序更多的考察的是我们方法的定义以及运用(C语言中叫做函数),为我们接下来在类中定义方法奠定了基础。

      ​ 首先考虑输入格式的合法性,在这里将检查合法性的代码封装在一个方法里,方便主函数的调用以及代码的整洁性。用if语句判断题目给出的条件,以及各个月份天数的合理性。

      ​ 在判断下一天的时候首先想到了在月份之间过渡的情况和年与年之间过渡的情况,如果处于过度的时候,再判断是月过度还是年过度。其次就是闰年以及平年的二月份过渡的情况,这些特殊除外,下一天就把天数单纯的加1就可以。

      Method CogC ev(G) iv(G) v(G)
      test3.checkInputValidity(int,int,int) 14 1 10 18
      test3.isLeapYear(int) 2 1 1 3
      test3.main(String[]) 1 1 2 2
      test3.nextDate(int,int,int) 14 1 8 21

      ​ 在检查合理性方法和求下一天函数中都使用了较多的判断语句,导致圈复杂度很高,应该进一步优化。

    2. 题目7-5

      ​ 7-5是题目7-4的进阶版,题目要求求下n天,不同的是在求下一天的函数传递一个n的参数,在判断合理性的函数中需要检查n的合理性。

      ​ 在我判断时,我首先想到n的情况,也就是分为求下n天,上n天和本天三种情况:在普通情况下则不必多说,只需在原天数上加n天或减去。问题在于过渡情况,求上n天时我解决过渡问题,想到的解决方法是将原天数加一个月份的天数,然后再减去一个n,得到的就是结果。

      ​ 下n天过渡时,只需在原天数上加一个负数的绝对值,然后进行除于操作即可。

      Method CogC ev(G) iv(G) v(G)
      com.my.java.Main.checkInputValidity(int,int,int,int) 16 1 11 20
      com.my.java.Main.isLeapYear(int) 2 1 1 3
      com.my.java.Main.main(String[]) 1 1 2 2
      com.my.java.Main.nextDate(int,int,int,int) 62 1 18 40

      ​ emmm,这个复杂度确实太高了(),需要进一步改进(甚至重写

  3. 第三次作业

    1. 题目7-2

      ​ 同样是求下一天,只是这次真正来到了面向对象编程,本次题目需要定义一个Date类,其中要求使用年月日三个私有变量,还有变量的修改和设置方法。将方法封装在自定义类里面,更能体现类的优点。这次练习虽然只是上一次作业的类表示法,但是最主要的是让我了解了类的基本设计。

      i

      Method CogC ev(G) iv(G) v(G)
      com.my.java.Date.Date() 0 1 1 1
      com.my.java.Date.Date(int,int,int) 0 1 1 1
      com.my.java.Date.checkInputValidity() 14 1 10 18
      com.my.java.Date.getDay() 0 1 1 1
      com.my.java.Date.getMonth() 0 1 1 1
      com.my.java.Date.getNextDate() 14 1 8 21
      com.my.java.Date.getYear() 0 1 1 1
      com.my.java.Date.isLeapYear(int) 2 1 1 3
      com.my.java.Date.setDay(int) 0 1 1 1
      com.my.java.Date.setMonth(int) 0 1 1 1
      com.my.java.Date.setYear(int) 0 1 1 1
      com.my.java.test3.main(String[]) 1 1 2 2

      从复杂度来看,还是在检查合理性上面占了较多的复杂度,需改进。

    2. 题目7-3

      ​ 这次的题目难度就较大了,一元多项式的求导,考察了对类,方法,字符串的综合应用。本题的解决方式最好是使用正则表达式,但由于我在写报告前还不甚了解正则表达式,于是想到把多项式拆成一个个的小式子并储存在一个数组中,方便计算。

      ​ 具体来说,首先输入一段字符串并去掉其中的空格,这样防止空串导致报错;在主函数中创建一个单项式的数组并初始化。将其他创建、检查合理性、检查字符等功能放入方法中,方便管理。

      ​ 在term_num这个方法中,按照单项式的每个字符依次检索,直到下一个单项式。这里while(true)循环能遍历整个单项式,并检查每个字符,将检测出的系数和指数分别存到单项式数组里。

      ​ 在Term类里,只定义了系数和指数两个私有变量,方便储存和调用。

      ​ 最后,我使用了StringBuilder类来创建一个求导后的新字符串,在不同的情况下添加不同的字符串,构造后返回所求的字符串。

      image

      Method CogC ev(G) iv(G) v(G)
      com.my.java.Term.getCoef() 0 1 1 1
      com.my.java.Term.getPower() 0 1 1 1
      com.my.java.Term.setCoef(int) 0 1 1 1
      com.my.java.Term.setPower(int) 0 1 1 1
      com.my.java.test4.dump_terms(int,Term[]) 13 3 10 11
      com.my.java.test4.main(String[]) 3 1 2 3
      com.my.java.test4.term_num(String,Term[]) 70 14 19 39

      ​ 复杂度分析可以看出在遍历过程中增加了太多的程序整体的复杂度,遍历这种暴力解法效率还是太低了。(如果能重来,我一定好好学习正则表达式)

三、踩坑心得

​ 刚开始学习OO,有不少细节上的坑容易忽视,慢慢来吧。

  1. 第一次作业

    1. 题目7-8

      ​ 这题最大的坑就是浮点数的运算情况,正好坑了我这个Java萌新,像a * a + b * b == c * c这样的判断条件可能只有我写的出来,之后看了书才知道浮点数之间运算是有误差的,判断小于10e-7就可以说明近似相等。正确的做法是a * a + b * b - c * c < 10e-6 或者使用BigDecimal类来得到准确结果(比较繁琐)

      ​ 测试数据:1.0 2.4 2.6

      ​ 应得结果:Right-angled triangle

      ​ 实际结果:General triangle

  2. 第二次作业

    1. 题目7-4

      ​ 这题的坑在于没想到只有30天的月份会输入31天的情况导致WA,导致有两个点没有通过。其他容易掉进去的坑在于2月的过渡情况,记得判断闰年。

    2. 题目7-5

      ​ 我以为这题只要稍微改动一下就能通过,没想到有很多需要注意的点。

      • 求上n天时,最主要的问题在于1月过渡到去年的问题。

      • 求下n天时,除于时用的天数一定要看清楚

      • 不要漏掉n = 0的情况

  3. 第三次作业

    1. 题目7-2

      ​ 这题和上一题差不多,只是表现形式不同,注意调用实例方法用.

    2. 题目7-3

      ​ 本题。。一言难尽。。对于刚学习类的我们是一个不小的挑战。本题基本上是通过看测试点提示才勉勉强强拿了40分,还有大数测试点需要重构整个程序。。

      ​ 首先常量测试一开始就没想到,发现常量测试没有输出,才发现没有考虑到,需要添加一个子串数目为0且指数为-1的判断语句,此时整式为0,输出为0。这里特别要注意的是,由于我方法上的缺陷,每次检索到式子中指数为-1的情况不一定是只有常数项的情况!!一定要加子串数量为1。顺便也解决了第一项、最后一项为常量的测试点。

      ​ 还是由于我程序的缺陷,第一项在类似12x这样的输入会在式子前错误的添加+,本应是12,结果输出+12,需要判断一下上一个式子的指数不能为0。

四、改进建议

优化代码。。减少复杂度。。

  1. 第一次作业

    1. 题目7-8

      ​ 将大量的if-else语句改进为 switch-case语句,减少不必要的判断。

  2. 第二次作业

    1. 题目7-4、7-5

      ​ 在求下一天的方法里,每个判断里有共同的语句,应只写一遍;判断语句应该减少,改用switch-case

  3. 第三次作业

    1. 题目7-3
      • 判断系数和指数的方法将我的暴力循环写法改成正则表达式法,能快速高效的找出系数和指数。
      • 由于java语言字符串结尾没有结束符,导致我只能在原字符串结尾加一个空格作为结束符,这一点也可以优化。
      • 由于不知道子串的数量,只能先new一个大小为100的数组,如果数据再多就会爆栈。。

五、总结

​ 首先学习到了Java基本语法的使用,最主要的是接触了一点面向过程编程的思想,通过踩了不少坑,最最最大的经验就是字符串匹配一定要用正则表达式来匹配。学会了如何测试、调试程序。

​ 我还有许多需要学习的东西,包括熟练使用正则表达式及其进一步的应用,还有关于类的进阶使用,包括多态、继承等,面向对象编程确实方便了不少,我还应多多实践,多做一些小项目,只有在踩了坑以后才会多注意坑。

​ 本次总结也让我收获很多,让我做总结了自己的不足,加深了记忆,收获颇丰,继续加油吧。。

人生苦短,我学Java

六、相关资料

  1. 降低复杂度的方法

    降低圈复杂度常用的方法有:
    
    简化、合并条件表达式
    将条件判定提炼出独立函数
    将大函数拆成小函数
    以明确函数取代参数
    替换算法
    
    降低认知复杂度的常用方法:
    1.减少if、for、while、do while、catch关键字嵌套,可以把深层次的代码抽象成方法。
    
    2.如果大量相似的if-else语句可以考虑用switch代替
    
    3.没啥规律就看见if、for等关键字提成方法
    
  2. Java Pattern 和 Matcher 库的详解

    https://blog.csdn.net/zengxiantao1994/article/details/77803960

  3. markdown的使用教程

    https://www.runoob.com/markdown/md-paragraph.html

  4. 图片使用

posted @ 2021-03-31 23:06  markbee  阅读(63)  评论(0)    收藏  举报