20172308《程序设计与数据结构》第七周学习总结
20172308 2017-2018-2 《Java程序设计》第七周学习总结
教材学习内容总结
继承
1.父类与子类,子类继承了父类的所有方法和变量,即使声明为private(会为变量预留内存空间,但不能按名引用父类private成员),但不会继承父类构造方法(因为那毫无意义)
2.子类有时会用到父类的构造方法,,需要用super引用(子类的构造方法第一行用super引用且必须是第一行,如果不写,Java会自动产生一行super())
3.Java不允许多继承(因为会无法处理好多个类中同名方法的引用),但是Java可以用接口来实现多个类的交互(这样就减少了歧义)
4.重写方法:子类出现与父类的相同方法名时,子类方法优先(重写父类方法,我觉得这也是继承的一种目的:比如一个类里的方法被另一个类继承之后,会根据自己类的特点重写适合自己这个的方法,比如,toString)
影子变量:合法但不提倡
5.所有的类都由object类派生
教材学习中的问题和解决过程
-
问题1:关于继承的第一个疑问就是:书上说“通过继承,新类自动包含了原始类的变量和方法,然后程序员可以将新变量和方法添加到派生的新类或者修改所继承的变量与方法”。那问题就是既然继承会自动包含原始类的变量和方法,那为什么不直接在原来的类里面改动呢,或者复制一下,怎么改动不都可以吗?不是更快捷方便吗?
-
问题1解决过程:百度。继承的意义确实很重要。
1.实际上,直接在原有代码上改是可以的,但问题是你不知道你的修改会对使用这个类的别的代码产生什么影响。
2.拷贝原代码再修改,这样原来的代码作者想要修正的bug,拷贝后的代码无法更新,bug依然保留。而且后期修改代码会很难修改。
3.继承还有一个作用:允许被调用者写出代码,同时允许调用者“填空”,实现对流程的复用(不是很懂)
4.继承实现了代码的复用,衍生出各种架构,抽象多态的解释,代码更优雅,代码组织架构更好。 -
问题2:书上说“protected的封装性不如private严格,但比public更强”。后面又说“声明为protected可见性的变量和方法除了可被子类引用外,还可以由同一个包内的任何类引用”。如果是这样的话,那还为什么要声明成protected,直接public不是一样的吗?即使是public,一个类想要引用另一个类也必须要放在同一个文件夹下才能引用啊?protected比public的封装性的强处完全没体现出来啊。
-
问题2解决过程:等待蓝墨云的解答。
【更新】emmm,突然为自己的智商感到了担忧......并不是非得要在一个包里才能调用另一个类,用import声明就好了(我竟然忘了这个......),另外尝试了王老师说的,如果另一个类里的变量声明是protected,如果不是它的子类调用它的话,就算是import也不可以。 -
问题3:书上说“构造方法不会被继承,子类拥有父类的构造方法是没有任何意义的,子类没有必要继承父类的构造方法”,“子类可能需要引用父类的构造方法”。目前所知道的构造方法的作用就是初始化变量。而直接在子类构造方法中设置变量可能比super引用更容易,但是父类如果做了修改,相应的子类构造方法中也要进行相应修改。如果是这样的话那为什么不直接继承过来?书上还说:“构造方法的第一行应该用super引用调用父类构造方法,如果不存在这样的调用,Java会自动在构造方法的开始处产生一行super()调用”既然是这样,跟继承好像也没什么区别,父类的变量继承过来也要初始化才能用吧。
-
问题3解决过程:百度。构造方法是特殊的方法,之所以不能继承是因为构造方法要与类同名,如果构造方法被继承,那么它肯定和子类的名字不同,而且他也没有返回值,编译肯定是通不过的。
代码调试中的问题和解决过程
-
问题1:课后习题PP9.1。编程要求在类里声明一个变量用于保存硬币面值,并要求编写一个main驱动类实例化对象并计算若干个对象的和。
-
问题1解决过程:自己思考+参考同学代码。按照我一开始的思考,写的代码如图:
首先要解决的是第一个问题是如何声明一个变量用于保存硬币面值,面值有很多种,所以这里很容易想到用一维数组来表示,然后设计一个方法来随机产生数组里的索引值,从而返回索引位置处保存的面值数。代码如图:
第一个方块的部分就是声明的用于保存硬币面值的数组,第二个方块就是所写的方法,将索引处的值赋给value。
而第二个要解决的问题是如何计算若干个对象的和。首先我想到的思路是:若干个就是用户想要多少个,所以第一张图所示,我设计了与用户交互,然后用for循环计算每一次产生出来的面值,再加起来。然而这个循环在运行的时候出现了两个问题:第一就是这个.flips()
方法,每一次循环产生的结果都是一样的,这让我意识到一个变量是行不通的,要产生多少个值,就需要多少个对象,这就让我的用户输入变得复杂了,因为要实例化的对象个数也是变化的(如果用数组的话应该也可以解决这个问题)。第二个问题就是我发现每次调用随机产生面值的方法并不是随机的,测试了一下,它只能产生数组中索引值为0处的面值大小,而如第二张图的第二个方块的代码所示,我写的方法应该没有问题。
本来是要接着写下去的,但是参考了其他同学的代码,发现我好像会错了意,若干个代码应该指的是我所保存的硬币面值的个数......于是重新写了代码如图:
按道理来说,应该符合题意的,但结果并不正确,我输出了三次的值(并且是用了三个对象),但最后的三个数的和并不正确。跟一开始想的一样,第一次对象a调用的flips方法产生了一个面值,但是我在算总和的时候又调用了一次,所以两次产生的值不同,计算的时候用的是后面产生的值。但问题是这就跟我前面发现的那个问题产生了矛盾,明明之前每一次调用同一个对象的同一个方法产生的值是一样的。。。无奈只好把产生的值赋给一个变量了,最终的代码如图:
还有上面说的那个为什么每次产生的面值总是数组里索引为0处的大小。我想了一下,一开始用的是Math类的random方法,然后乘的3,感觉不妥,于是换用了random类的nenxtInt方法,最后解决了问题。 -
问题2:课后习题9.3。题目要求写一组类,在每个类中定义描述其各种属性的值和输出相应信息的方法,最后创建main驱动类实例化并使用这些类。
-
问题2解决方案:首先看到这个题目的时候,我觉得有三种做法。我自己只做了第一种最简单的方法(如果有时间我想尝试一下剩下两种做法,然后在博客下面补充更新)。如图是我写的驱动类和其中一个类的代码:
直接将类实例化,写好实参,再挨个输出就行了。而类里,在构造方法里设置好形参,写两个返回信息的方法,再写个toString就结束了。这样勉强算是完成了题目的要求,但很显然没怎么用到本章知识。
所以说到这第二种方法就是利用本章的继承,只要在开始extended相应的类就好了,但是在写的时候,有个问题就是,Java是不支持多继承的,所以没办法在一个驱动类程序中使用这些类(如果把他们写成接口应该就可以了),所以这种方法要用的话就要为每个类写一个驱动类程序(很麻烦......),也不怎么符合一个main驱动类的题意,而且继承的话,如果不是要用到具体返回某个属性值的话,也用不上继承,在构造方法里写就足够了。
第三种方法我觉得是最综合的,应该能行的通吧。我的设想是,直接在一个类里面声明一个数组,用于储存这些类,然后在下面分别编写这些类,这样在写驱动类程序的时候,只要
继承这一个类,就可以通过调用数组里特定索引处保存的类及其中的方法。
代码托管
上周考试错题总结
-
错题1:
-
错题1解析:数组被初始化为= new type[x],其中x是数组的大小。然而,该数组的法律索引为0到x - 1,因此,程序员通常都是离线的,因为程序员将编写代码来尝试访问索引1到x。
-
错题2:
-
错题2解析:参数被定义为变量最初被声明为类型参数名称。这里,类型为int[],参数为a。
-
错题3:
-
错题3解析:第一次银行帐户;为firstentity银行保留内存空间,它本身是指向BankAccount[]对象的引用变量。第一次银行账户=新银行账户[1000];实例化BankAccount[]对象为1000个BankAccount对象。这意味着第一个帝国银行[0]和第一个帝国银行[1]和第一个帝国银行[999]现在都是合法的引用,每一个都是一个参考变量,因为每个引用都是一个BankAccount对象。因此,语句保留了1000个引用变量的内存空间。1000个BankAccount对象都没有实例化,因此没有为任何实际的BankAccount对象预留内存。
-
错题4:
-
错题4解析:数组索引必须是一个int值,所以如果x不是int,那么通常值[x]会导致语法错误,但是Java编译器会自动将x转换为int,如果它可以被转换的话。字符通过将char值转换为等效的ASCII值来转换为int类型。因此,如果x是'a',它被转换为int 97,因此值[x]访问值[97]。
-
错题5:
-
错题5解析:“=”是一个赋值运算符。如果两个变量都是原语,比左边的变量副本右边变量(如果a和b是int值,b = 5,然后将成为5)。然而,因为a和b是数组的引用变量设置为参考变量b,导致a和b都引用同一个数组在内存中,或者他们现在彼此的别名。
-
错题6:
-
错题6解析:主方法需要参数,以防程序员希望允许用户提供命令行参数。在java命令之后,在命令行输入的任何内容都将被接受为命令行参数。如果是由空格分隔的几个单词,那么每个单词都作为一个单独的字符串数组元素存储。例如,“java foo。class hi there“将在变量[0]和变量[1]中存储“hi”,以供程序使用。
-
错题7:
-
错题7解析:数组被称为同构类型。这意味着存储在数组中的值的类型必须与每个元素相同。类型由声明决定。因此,int[] x只使x为int值的数组。因此,没有数组可以存储双精度和字符串。
-
错题8:
-
错题8解析:数组的一个缺点是它的固定大小。一旦实例化,它的大小是固定的,因此,如果一个程序试图添加比数组大小更多的元素,它会导致一个异常被抛出。ArrayList是一个使用数组的类,它会自动创建一个更大的数组,将旧数组复制到新数组中,这样ArrayList就可以根据需要更大。虽然这可以解决抛出异常的问题,但它确实会导致性能较差,因为每次增加ArrayList大小时,必须从一个数组复制到另一个数组。
-
错题9:
-
错题9解析:ArrayList是作为数组实现的,只要其中一个只是访问ArrayList的元素,效率与数组的效率是一样的。但是,当对ArrayList的前部分进行插入或删除时,就会发生大量的元素复制,从而降低其效率。
结对及互评
-
博客中值得学习的或问题:
- 侯泽洋同学的博客排版工整,界面很美观
- 问题总结做得很全面
- 对于书上的疑惑总会想办法解决它,这种探索的精神值得我去学习
-
代码中值得学习的或问题:
- 对于编程的编写总能找到角度去解决
-
本周结对学习情况
- 20172302
- 结对学习内容
- 第九章内容
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 309/309 | 1/1 | 20/20 | |
第二周 | 269/578 | 1/2 | 18/38 | |
第三周 | 236/776 | 1/3 | 22/60 | |
第四周 | 507/1283 | 2/5 | 30/90 | |
第五周 | 631/1914 | 1/6 | 30/120 | |
第六周 | 529/2443 | 1/7 | 25/145 | |
第七周 | 515/2958 | 1/8 | 25/170 |