OO第一次博客作业
一、前言
以前对面向对象有过一点基础的认识,再加上自己自学过部分C++,以及良好的编程能力,所以刚开始学起来还是挺轻松的。
经过前三周系统的学习,现在对面向对象也有了一些初步的认识。个人认为面向对象更应是一种思维,是一种面对对象的设计的编程思维。
我们学习面向对象使用的是Java语言,Java的一些语法与C和C++有些不同,Java更多地借鉴了C++的优点,而摒弃了它的一些不太容易被人掌握的知识点(有些不能说是缺点),并且增加了一些自己的特点,使得其更贴合使用者,使使用者们更容易接受。但Java也并不是完美的,它也有一些自己的缺陷。
Java具有跨平台的特性
跨平台特性的最大优点就是只要有相应的运行环境,同一个编译好的程序就能在上面运行,而不需要重新编译程序,它的缺点就是不能针对特定平台,所以不能充分利用平台特性,因而在性能上会有所降低,幸运的是现在的硬件比以前大大提高,这部分的降低在绝大部分情况下可以不用考虑。而且Java有自动垃圾回收机制,运行时环境可以自动清理不再使用的内存,减少了手动释放内存的风险。Java的跨平台特性建立在可以跨越多个不同种类的操作系统平台,比如Windows、Linux、Unix等,但是需要注意的是不是说Java能在所有的系统上都能跨平台,必须实现在该操作系统上的Java运行时环境JRE才行,也就是说假如今天有人开发了一个前所未有的系统,这时候Java程序是不能在上面运行的——因为还没有针对这个操作系统的Java虚拟机(JVM),好在在当今绝大部分操作系统上都有针对该系统的JVM,所以它能“一次编译,到处运行”。
语法特性
Java抛弃了指针,使用了包(package)的概念,导入包使用import语句,在Java中有几种非面向对象的数据类型,那就是byte、char、short、int、long、float、double这几种数据类型,在方法中传递时仅仅是传递它们的值,为了方便一些集合类的操作(它们存储的是对象类型),又增加了它们的包装类Byte、Char、Short、Integer、Long、Float、Double。在Java中存在属性的概念,这些都是通过setXXX()、getXXX()来设置。
关于Java的类
Java的类有些类似C++的结构体,其中都可以创建构造方法以及其中对相关信息的操作的方法。C++支持重载运算符,Java里也有重载这个关键词,但其是对其父类中的成员方法的重载,并不支持运算符的修改。Java的类支持继承的功能,在保留父类的相关特点的情况下还可以对相关的特点进行扩展,使得其可以根据自己的特点发挥出更加具有方向性的特性。Java中的重写及重载更是使得其子类有着更多的扩展性,更符合自己的特点。重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。而重载更是体现了Java的多态性,是Java多态性的具体表现。Java的封装性可以将函数接口的实现细节包装, 隐藏起来,而防止该类的代码和数据被外部类定义的代码随机访问。
经过这三次的作业,我也有了不少的收获。
二、作业分析
第一次作业(判断三角形类型)
由于第一次作业,还没有面向对象的思维,所以第一次作业的代码就完全没有面向对象的风格,也就是多次套用if-else语句。
不出意外,复杂度很高。
后来为三角形独立地创建了一个类,虽然复杂度上并没有很好地优化,但更符合了面向对象的思想。
当初有一个测试点不知为何过不了,后来仔细思考了一下,发现因为是实数型运算,可能会有精度误差。在增加精度的容错后,果不其然终于过了。
第二次作业1(求下一天)
这道题里明确规定了需要创建相关方法,来判断日期。
一开始求每月天数使用了许多if-else,复杂度很高。后来思考了一下,将每月天数存储在数组中查询时直接调用比较,将该部分复杂度降至O(1),而在判断2月的天数时只要再特判一下是否是闰年就行了。
在判断输入日期是否非法时,只要判断输入年月是否超出边界,而日只要判断是否是正数,并且是否超出对应的月份天数就行了。
而在求取下一天的方法中,将天数加1,判断是否超过当前月份天数,超过就将天数归1,并且月份加1。月份也一样,超过12就将月份归1,并且年份加一。
复杂度也还行,目前也没有找到更好的优化方法。
第二次作业2(求前N天)
这应该是上一题的进阶版吧,现在求的是前X天(不光是一天),并且还包含了求后X天。
但相较于上一题其实并没有太多的大改动,只需要在判断结果天数的方法中把天数加1改为加对应的n天就行了,其他并没有什么大改动。
复杂度高了一点,应该是因为要判断输入的天数是大于0(前n天)还是小于0(后n天)。
第三次作业1(定义日期类)
这道题主要目的明显,就是要创建一个日期的类,以练习类的相关操作。
而输出则是和上一次的作业1一样,但这次是要使用类来完成。
对应类图:
以及对应类的代码
public class Date { private int year = 0; private int month = 0; private int day = 0; int[] mon_maxnum = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; public Date() {} public Date(int year, int month, int day) { this.year = year; this.month = month; this.day = day; } public int getYear() { return this.year; } public void setYear(int year) { this.year = year; } public int getMonth() { return this.month; } public void setMonth(int month) { this.month = month; } public int getDay() { return this.day; } public void setDay(int day) { this.day = day; } public boolean isLeapYear(int year) { if((this.year % 4 == 0 && this.year % 100 != 0) || this.year % 400 == 0) return true; return false; } public boolean checkInputValidity() { boolean flag = false; if(this.year < 1900 || this.year > 2000 || this.month < 1 || this.month > 12 || this.day < 1 || this.day > 31) return false; if(this.isLeapYear(year)) flag = true; if((this.month == 2 && flag && this.mon_maxnum[this.month] + 1 < this.day) || (this.mon_maxnum[this.month] < this.day && !flag)) return false; return true; } public void getNextDate() { int d = this.day, m = this.month, y = this.year; int[] a = this.mon_maxnum; d++; if(this.isLeapYear(y)) a[2]++; if(d > a[m]) { d -= a[m]; m++; } if(m > 12) { m -= 12; y++; } System.out.println("Next day is:" + y + "-" + m + "-" + d); } }
而主函数中则是简单的调用checkInputValidity()方法检测输入是否合法,最后再输出对应结果。
通过这道题,也让我对类的创建和使用以及面向对象的思维和特点有了一个基础的认识。就像在主方法中,只用调用对应的方法就行,而不用管类中的相关信息,这很好地 体现了类的封装性。
第三次作业2(一元多项式求导)
这应该是目前遇到的唯一一道具有一些难度的有题目了, 它的难点在于对字符串的处理。
由于正则表达式的存在,再处理字符串时可以方便不少。由于正则表达式的内容不多,难度也一般,所以是通过自学的方式来掌握的。
另外,由于测试数据中有大数的测试点,所以还去查阅且学习了关于Java中的BigInteger类(所谓的高精)。
经过一段时间的仔细学习和调试,就初步完成了这道题的源码。
由于第一次提交,并没有想着去优化,只想着能通过就行,所以代码非常冗长且复杂。
但是并没有通过所有的测试点。
经过一番优化和修改,去除许多冗余的判断并且简化代码后再一次提交,比上一次提交多过了一个测试点。
后来的多次修改优化都无法通过最后一个测试点,目前也还在思考中,不知道忽略了哪一个细节。
三、总结
在这三个星期的学习中也学到了很多,收获了很多。对于面向对象的思维也初步了解了许多,如对类的设计和调用等相关操作。
在对代码的改进过程中,也掌握了和积累了一些经验,懂得使用一些更优的算法去优化整体结构。并且码风也有了一些的改善,更清晰易懂,且懂得适当地增加注释。
当然还有许多的不足之处需要在今后的学习中去逐步完善。