20155232 2016-2017-3 《Java程序设计》第4周学习总结
教材学习内容总结
- 第六章 继承与多态
所谓继承就是避免多个类间重复定义共同行为。
1.重复在程序设计上就是不好的信号,如果要改进就可以把相同的程序代码提升为父类。
2.使用新的关键字extends表示继承并且扩充原先没有的行为。继承的好处就是若要修改,无需在继承的子类中去修改。
注意private成员会被继承,不过无法直接存取,必须通过父类提供的方法存取。
3.子类只可继承一个父类,子类与父类之间会有is-a的关系。
例如:
Role role1 = new SwordsMan()
SwordsMan swordsman = role1; //x
SwordsMan swordsman = (SwordsMan)role1; //ok
第二条语句会出现编译错误。第三条语句在执行时会抛出classcastexception。
4.多态
使用单一接口操作多种类型的对象
5.重新定义
定义与父类中相同的方法部署,但执行的内容不同(override)。
在JDK5之后,内建标注
@Override
如果在子类的某个方法前标注,表示要求编译程序检查该方法是不是重新定义了父类的某个方法。
6.抽象方法,抽象类
如果某方法区块中真的没有任何程序的代码操作,可以使用
abstract
标示该方法为抽象方法。
注意抽象类不能使用new生成对象
7.protected成员
相同包中的类可以直接存取,不同包中的类可以在继承后的子类中直接存取。
public / package / protected / private
提示依照权限由小至大来区分就是private,无关键字,protected,与public。
8.重新定义的细节
如果想取得父类中的方法定义,可以在调用方法前加上super关键字。
可以使用super调用父类方法,不能定义为private。
注意重新定义方法时,对于父类中的方法权限,只能扩大不能缩小。
9.再看构造函数
构造函数可以重载,父类中可重载多个函数。如果想执行父类中某构造函数,可以使用super()指定。
注意this()与super()只能择一调用,而且要在构造函数第一行执行。
10.再看final关键字
class前也可以加上final关键字,表示这个类是最后一个类,不会再有子类,即就是不能被继承。
定义方法时,也可以使用,表示子类不可以重新定义final方法。
11.java.lang.Object
如果继承时没有使用extends关键字指定任何类,那么继承的是java.lang.Object。
12.instanceof运算符可以用来判定对象是否由某个类创建,左操作数是对象,右操作数是类。
13.垃圾收集
无法通过变量引用的对象就是GC认定的垃圾对象。
垃圾回收前会调用finalize()方法,但由于调用时机无法确定,建议不要使用finalize()方法。
- 第七章
1.使用接口(interface)定义行为
类要操作接口,必须使用implemnts关键字。
操作接口时,对接口中定义的方法有两种处理方式,一是操作接口定义的方法,二是再度将方法标示为abstract。
继承与操作接口的区别:继承时有“是一种”的关系,操作接口则表示“拥有行为”。
2.如果增加新的需求,原有的程序无需修改,只需要针对新需求撰写程序,就是有弹性,具有可维护性的程序
3.类可以操作的两个以上的类,也就是拥有两种以上的行为。
4.接口默认
在接口中枚举常数,一定要使用=指定值,否则编译错误。
注意要在类中定义枚举常数也是可以的,不过要明确写出public static final。
5.匿名内部类
在撰写java程序的时候,会面临临时继承某个类或操作某个接口并建立实例的需求,由于只使用一次,不需要定义名称。可以使用匿名类。
在JDK8之前要在匿名内部类中存取局部变量,必须是final,否则编译错误。
注意局部变量的生命周期比对象短。java的做法是传值。
6.使用enum枚举常数
enum实际上定义了类,而enum中列举的常数,实际上是public static final ,且为枚举类型实例,无法撰写程序直接实例化枚举类型,因为构造函数权限设定设定为private。
教材学习中的问题和解决过程
- 在第六章刚开始时,书上提到不能滥用继承,那么滥用继承会导致什么样的后果?
首先我上网搜索了一下怎么样才算滥用继承。
两个判定是否是滥用继承的重要依据:
1.如果一个类从核心用意和设计初衷上天然是另一个类的子类,这种继承是天经地义的,并不存在破坏封装的说法。
2.在允许多继承的语言里,如果一个类需要使用到来自另一个父类(特质)的“全体”字段和方法,或都反过来说,把某个父类(特质)的全体成员赋予另一个类时,如果从这两个类的设计用意和代表的概念上没有任何的违和感,那么,这时候使用继承也是正当的,没有破坏封装的嫌疑。
那么危害有哪些呢?
- 2.书上提到在重新定义方法中,要注意,对于父类中的权限,只能扩大不能缩小,为什么?
- 举个例子,在父类中是public的方法,如果子类中将其降低访问权限为private,那么子类中重写以后的方法对于外部对象就不可访问了,这个就破坏了继承的含义。
代码调试中的问题和解决过程
- 在输入p161代码后,如下:
但是运行不出书上的结果:
剑士:(Justin, 1, 200)
魔法师:(Monica, 1, 100)
而是出现如下错误:
- 解决方案:
将代码加入,将两段代码合并!
在编译后又会报错,因为出现了两个public,所以再次修改:
class Role {
private String name;
private int level;
private int blood;
public int getBlood() {
return blood;
}
public void setBlood(int blood) {
this.blood = blood;
}
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level= level;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void fight(){}
}
class SwordsMan extends Role{
public void fight(){
System.out.println("挥剑攻击");
}
}
class Magician extends Role{
//private String fight;
public void fight(){
System.out.println("魔法攻击");
}
public void cure(){
System.out.println("魔法治疗");
}
}
public class RPG3 {
public static void main(String[] args) {
SwordsMan swordsMan=new SwordsMan();
swordsMan.setName("Justin");
swordsMan.setLevel(1);
swordsMan.setBlood(200);
Magician magician=new Magician();
magician.setName("Monica");
magician.setLevel(1);
magician.setBlood(100);
drawFight(swordsMan);
drawFight(magician);
}
static void drawFight(Role role){
System.out.println(role.getName());
role.fight();
}
}
运行结果:
- 因为课本上给出的基本上都是代码段,刚开始不知道怎么同时运行两个程序(子类和父类),也不不知道如何编译,在查阅相关资料,问了同学之后,要将两个程序放在一个package中,然后先编译父类,在编译子类,最后运行即可。下面是过程的截图。
1.在同一个包(Array)中建立两个文件
2.并在两个代码段的开头都加入了
Package Array;
表示在同一个包中。
3.开始编译Guest代码段,出现错误
原因:未先编译父类的方法。
4.先编译父类的方法ArrayList.java在编译Guest.java:
5.最后在运行时又出现了错误如上图
6.修改如下:需要将写上 package的名称.代码段名称
(并且运行)
问题解决~!
代码托管
代码提交过程截图:
代码量截图:
脚本截图
上周考试错题总结
- 1.填空:Linux Bash中,(grep )命令可以进行全文搜索。
原因:linux的命令掌握的还不够熟练,很多命令因为不常用就容易忘记。
- 4.填空:System.out.println(“”+52+25);的结果是(5225)
- 5.填空:System.out.println(52+25+””);的结果是(77)
原因:这个我现在也不太懂,希望老师能讲解一下疑惑。
- 19.CH04 填空:“30”转化为byte类型的30的语句是(Byte.parseByte(“30”);)。
原因:看书的时候这里没有仔细阅读,看书上给出的例子,不够熟练应用于实例中,还不够熟练掌握,做到举一反三。
感悟心得
- 对教材感悟
在第六章中了解了继承的目的,继承就是避免多个类间重复定义共同行为,并且在修改过程中也避免了很多麻烦。还了解了多态与继承的关系,并且通过阅读教材大概知道了如何重新定义方法,重新定义时且若要取得父类中的方法定义,对于父类的方法权限,只能扩大但不能缩小。还知道了java.lang.Object是所有类追溯到最上层的父类。垃圾收集就是无法通过变量参考的对象,就是GC认定的垃圾对象。在第七章中,举例子介绍了接口定义行为,了解了接口的多态操作。两种方法的枚举常数。
- 对考试感悟
这次考试比前两次的成绩提高了2分,很开心。因为这次看书看得比较仔细,所以翻书找的时候没有浪费太多时间,所以时间上相对充裕了,题也写完了。还需要在代码上多下功夫,做到每天都要敲代码。
- 课本中代码的部分展示与思考
p159页代码如下:
public class Role {
private String name;
private int level;
private int blood;
public int getBlood() {
return blood;
}
public void setBlood(int blood) {
this.blood=blood;
}
public int getLevel() {
return level;
}
public void setLevel(int level){
this.level=level;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
}
接着使用SwordsMan可以如下继承:
出现了新的关键字extends,表示会扩充Role的行为,也就是继承,扩充了原本没有的fight行为。
Magician也可以进行继承:
p178页 定义的ArrayList类,可以不限长度收集对象,每次收集的对象会放在next索引处,使用size()方法得知已收集的对象个数。
注意如果使用无参数构造函数,则默认容量为16。
p186
定义的抽象类,这个类是不完整的,所以显示输入输出就不能操作。
p187继承抽象类GuessGame:
将3个代码段放在同一个包下(Iheritance)
p186-187猜数字程序
也是将代码片段放在同一个package中,然后分别编译,最后运行。
p197-201
Oceanworld程序,了解了接口和继承的区别,以及优势。并了解了
interface
implements
关键字的定义及用法。继承会有“是一种”关系,操作接口则表示“拥有行为”所以会优先考虑接口而不是继承。
课本编海洋的程序:
在输入p202页Airplane代码段时
课本上代码出现错误:
package OceanWorld1;
public class Seaplane implements Swimmer,Flyer {
private String name;
public Seaplane(String name) {
this.name = name;
}
@Override
public void fly() {
System.out.printf("海上飞机 %s 在飞%n", name);
}
@Override
public void swim() {
System.out.printf("海上飞机 %s 航行海面%n", name);
}
}
按照课本输入的Airplane.java但是代码为:
public class Seaplane ....
所以重新建立文件名,并进行编译,如下修改编译正确:
p209页程序:
p216
使用了匿名内部类。
与209页程序作对比,使用enum定义,不像之前play()方法可以传入任何int值,所以不需要使用default进行检查。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 15/15 | 1/1 | 23/26 | |
第二周 | 208/240 | 2/2 | 35/38 | |
第三周 | 376/584 | 3/3 | 32/38 | |
第四周 | 823/1407 | 4/4 | 28/30 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
计划学习时间:28小时
实际学习时间:30小时