Java第二阶段学习总结

前言:在第二个阶段的学习中三次作业的一次小结,使我们进一步加强了对面向对象与单一职责的了解,是一次对面向对象编程更深入的了解。

一、作业过程总结:

  1.总的来说,第二阶段的作业相比于第一阶段在难度和代码量上都有了很大的提升,这需要我们培养严谨的逻辑联系与夯实Java的基础。第一次作业中出现的正则表达式是一个难点,它需要我们全方面的对一个表达式考虑,如是否符合格式、考虑特殊情况等等,正则是一门新的学问,在今后的的学习与工作中的重要性不言而喻,应尽快投入学习。在第二次作业中,难点是多项式求导这一道题,这一道题中的难点:1)正确的分析多项式的求导,比如把多项式分解成单项式有几种类型,他们的导数该如何表示。2)该如何去校验输入的多项式是否每一个单项式都合法。这其中的考点:正则表达式的使用、类的继承与多态,Java中常用类的用法,例如ArrayList、LinkedList、StringBuilder、StringBuffer等。第三次作业则相对前两次难度略微降低,主要考察了ArrayList泛型的应用方法、Comparable接口及泛型的应用、单一职责原则的应用、“开-闭”原则的应用。并且第一次接触时间复杂度与空间复杂度的概念,这就需要利用算法来巧妙地实现转化。例如:

  在对于求n以内的多个素数时,不同的算法时间和空间的复杂度是不同的,当我们追求世间的简短时,就不可避免地加大了空间的内容,以下的几种算法参考自:https://blog.csdn.net/XlxfyzsFdblj/article/details/81149668

  1)穷举法

  时间复杂度为:O(n^2)

public class PrimeNumber {

    /**
     * 穷举法,检测所有可能的因子。
     * 时间复杂度为:O(n^2)
     */
    public void primeNumber1(int n) {
        int number = 2;
        int count = 0;
        while(number <= n) {
            boolean isPrime = true;
            for(int divisor = 2; divisor <= number / 2; divisor++) {
                if(number % divisor == 0) {
                    isPrime = false;
                    break;
                }
            }
            if(isPrime) {
                count++;
            }
            number++;
        }
        System.out.println("\ncount: " + count);
    }

  2) 检测直到√n的素数因子

  时间复杂度为:O(n√n / logn)
  

public void primeNumber3(int n) {
        int number = 2;
        int count = 0;
        int squareRoot = 1;
        int[] primes = new int[n];
        while(number <= n) {
            boolean isPrime = true;
            if(squareRoot * squareRoot < number) {
                squareRoot++;
            }
            for(int k = 0; k < count && primes[k] <= squareRoot; k++) {
                if(number % primes[k] == 0) {
                    isPrime = false;
                    break;
                }
            }
            if(isPrime) {
                primes[count] = number;
                count++;
            }
            number++;
        }
        System.out.println("\ncount: " + count);
    }

  3)* 欧拉筛选法

  时间复杂度为:O(n)

  

public void primeNumber5(int n) {
        int[] primes = new int[n + 1];
        boolean[] isNotPrime = new boolean[n + 1];
        int count = 0;
        for(int i = 2; i <= n; i++) {
            if(!isNotPrime[i]) {
                primes[count++] = i;
            }
            for(int j = 0; j < count; j++) {
                if(i * primes[j] > n) {
                    break;
                }
                isNotPrime[i * primes[j]] = true;
                if(i % primes[j] == 0) {
                    break;
                }
            }
        }
        System.out.println("\ncount: " + count);
    }

  结果输出:

  当我们输入148933时,可以得到如下结果:

count: 148933
primeNumber1 所用时间为(单位毫秒):294368

count: 148933
primeNumber3 所用时间为(单位毫秒):165

count: 148933
primeNumber5 所用时间为(单位毫秒):31

  这就说明了算法可以改变时间复杂度与空间复杂度之间的关系。

  2.封装性在每一道题中均有体现:把普通的对象进行封装,对象的属性设为私有的,对外提供get和set方法,其他类只能通过get和set对对象属性值进行操作。继承性就是生在两个类之间,一个类继承另一个类是说这个类属于另一个类,具有另一个类的所有属性和方法,同时它还可以有另一个类不具备的方法和属性。如triangle和rectangle类均继承自Shape类,因此可以继承Shape所以不是私有的对象和方法,换个角度也很好理解,Shape属于父类,属于一个很大的范围,而Triangle和Rectangle和只是子类,很小的一个分支,这也是面向对象的一种思维。多态是建立在继承的基础上的,一个父类对象可以产生多个不同的子类对象,根据这些子类对象的不同可以具备不同的方法,比如作业中出现的Comparable方法的重写可以改变排序的方向位置等操作,大大地加强了Java的可延展性与灵活性。

  3.出现的问题:对ArrayList类的一些方法不理解,通过查找百度等资料学习而来,还有一些正则表达式的使用,都可以利用丰富的网络资源来获得答案,此外,还能通过与同学讨论来获得。比如这有一个我和同学讨论过的一个问题:比较四个数中最大的数:1)可以用数组存入这四个数然后遍历求最大值。2)利用Math类中的比较方法:

double x=Math.max(sum1, sum2);
double y=Math.max(sum3, sum4);
double z=Math.max(x, y);

  我认为这个相比于用数组来计算最大数是更优的算法。

  4.时间比例:第一次作业中第一题水文校验花费了很多时间,却依然没有解决。在第二次作业中出现的对多项式求导也只是勉强及格,这还是自己基础的不扎实的问题,还需多加努力。在第三次就有了一些改善。也许是由于题目难度的降低,是三次作业中唯一的满分。

  5.认识:在每一道题中不管输入和输出都有着严格的标准,一没有达到就通过不了测试,因为Java也是一门追求严谨性与逻辑性的语言,在很多地方均有体现,从正则的校验到每一个数据的读入与输出,我在写作业中就遇到过一个空格导致错误的问题,也花费了很多的时间去找,这就告诉我时时刻刻必须有严谨的思维,切不可马虎了事,导致程序都是bug,对自己和别人都不方便。

二、OO设计心得:

  1.首先封装能实现对一些变量的保护,提高了安全性,并且能把代码分成一个一个的模块,有利于后期的维护,也提高了可复用性。继承即派生子类,可以有无穷多个子类,每个子类可以继承父类的属性与方法,并且还能有自己的方法,极大地节省了空间,避免了重复代码的出现,也表现出了延展性。多态在使用过程中往往联系的内容较多,牵一发而动全身,这样有利于代码的扩展,灵活性强。

  2.单一职责在例题中大量体现,如一个类只要完成本类的方法与属性,完全无需干预其他的类与对象,比如在多项式求导这道题中,我们可以将多项式分为一般单项式和常量多项式,求导方法单独封装,只需在使用时把多项式引入,即可求导,这表现出了它的可移植性,如果以后需要使用这个方法是,只需直接将此类导入,节省了时间和空间,也为自己和他人带来了便利。开闭原则则是对于扩展是开放的,对于修改是关闭的,即我们可以对原有的方法进行拓展以达到我们想要的效果,而无需自己从头开始写代码,也是一种便利性的体现。

  3.在以上提到的基本原则中,带给我关于面向对象编程的理解是写代码就像完成一件艺术品,我们首先得有一个总体的认识,即清楚自己想要达到的目的是什么,然后把大问题细分成一个个小问题,通过单一职责把它细分到每一个类每一个方法甚至每一个对象,然后一个个类完成,即区块化完成,当所有的类都完成后,在通过一个主类将他们完整的联系在一起,这也就是完成一件艺术品的收尾部分,所有模块都完成后,怎样把每一个模块毫无缝隙地连接在一起,这是需要下功夫的,当然之前的每一个类的设计也需慎重考虑,尽量能写出一些优秀的代码,展现给大家一件完美的“艺术品”。

  4.类的设计心得:首先应该考虑的是类的逻辑性与正确性,在此基础上进行改进,将它变得可延展,可复用,坚持单一职责与开闭原则,加以适当的注释,方便以后的阅读与维护。

三、测试的理解与实践

    普通测试:Ignore(忽视),Text(测试),Test(timeout = 1000)(限时测试),Test(expected = ArithmeticException.class)(异常测试)

    特殊测试:批量参数测试,打包测试等进行测试,是可行的。

四、课程收获:

  1.对面向对象的思维及一些基本原则的认识与使用,认识到代码严谨性的重要性。

  2.夯实了Java基础,了解了一些常用类的常用方法。

  3.写代码的熟练度渐渐提升,减少了语法错误的出现,也提升了写代码的速度。

五、对课程的建议:

  建议:第二阶段的题目难度明显有了提升,第三阶段希望进一步提升难度,但不要过大,应该给我们一个过渡期,不需要太难,但也不能简单,这样我们的能力才会慢慢地进步,而不会因为题目过难二崩溃,适当的到一些写出题的喜悦反馈,也是我们不断前进的动力源泉。

  在课程方面:老师已经讲的很不错了,希望能对一些经典代码进行讲解,在题目中出现的难点反复讲解。

 

posted on 2020-05-02 16:07  Max'  阅读(252)  评论(0)    收藏  举报