20145105 《Java程序设计》第4周学习总结
20145105 《Java程序设计》第4周学习总结
教材学习内容总结
第六章 继承与多态
一、何谓继承
(一)继承共同行为
-
继承基本上就是避免多个类间重复定义共同行为。
如:下述代码将剑士与魔法师定义时的重复程序代码归在一起。
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; } }
-
使用
extends
继承父类,并扩充父类没有的行为。public class SwordsMan extends Role{ public void fight(){ System.out.println("挥剑攻击"); } }
和
public class Magician extends Role { public void fight(){ System.out.println("魔法攻击"); } public void cure(){ System.out.println("魔法治疗"); } }
-
通过下述代码可以看出,子类中并没有定义的一些方法的确继承了父类的定义。
public class RPG { public static void main(String[] args){ demoSwordsMan(); demoMagician(); } static void demoSwordsMan(){ SwordsMan swordsMan = new SwordsMan(); swordsMan.setName("Justin"); swordsMan.setLevel(1); swordsMan.setBlood(200); System.out.printf("剑士:(%s, %d, %d)%n", swordsMan.getName(), swordsMan.getLevel(),swordsMan.getBlood()); } static void demoMagician(){ Magician magician = new Magician(); magician.setName("Monica"); magician.setLevel(1); magician.setBlood(100); System.out.printf("魔法师:(%s, %d, %d)%n", magician.getName(), magician.getLevel(),magician.getBlood()); } }
运行结果
- 优点:若要修改一些共同行为,只需要修改父类就可以了,只要是继承的子类都不用修改。
(二)多态与is-a
-
在java中,子类只能继承一个父类,子类与父类间有is-a关系,即“是一种关系”。
-
要保证语法逻辑正确,就必须保证=号右边是一种左边,即右边是左边的子类,否则就会编译失败。
-
用
Swordsman swordsman = (Swordsman) role1;
可以让编译程序忽略语法逻辑的错误,但执行时可能出现错误。 -
多态就是使用单一接口操作多种类型的对象。如下,既可以用Role类型操作Swordsman对象,也可以通过Role类型操作Magician对象。
public class RPG2 { 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); showBlood(swordsMan); showBlood(magician); } static void showBlood(Role role) { System.out.printf("%s 血量 %d%n",role.getName(),role.getBlood()); } }
运行结果
(三)重新定义行为
- 重新定义:在继承父类后,定义与父类中相同的方法部署,但执行内容不同。(因为对父类已定义的执行方法不满意,所以在子类中重新定义执行)
- 如果子类定义的与父类不同,就不是重新定义了,而是子类新定义了一个行为,编译时不会出错,运行时可能出现问题。
(四)抽象方法、抽象类
- 如果某区块中真的没有任何程序代码操作,可以使用abstract标示该方法为抽象方法,该方法不用撰写{}区块,直接“;”结束即可。
- java中规定内含抽象方法的类,一定要在
class
前标示abstract
。 - 子类如果继承抽象类,一种做法是继续标示abstract,另一种是操作抽象方法,如果两种做法都没有实施,就会引发编译错误。
二、继承语法细节
(一)protected成员
-
被声明为protected的成员,相同包中的类可以直接存取,不同包中的类可以在继承后的子类里直接存取。如下:
public class Role2 { protected String name; protected int level; protected int blood; ...略 }
在子类中就可以如下定义
toString()
public class Swordsman2 extends Role2{ public void fight(){ System.out.println("挥剑攻击"); } public String toString(){ return String.format("剑士(%s, %d, %d)",this.name,this.level,this.blood); } }
-
Java中有public、protected、与private三个权限关键字,但实际上有四个权限范围。
(二)重新定义细节
-
重新定义也可以只在执行父类方法的前后做点加工。
-
如果想取得父类的方法定义,可以在调用方法前,加上
super
关键字如下,在父类中定义toString()方法
public class Role2 { ...略 public String toString(){ return String.format("(%s, %d, %d)",this.name,this.level,this.blood); } }
如下,在子类中重新定义toString()方法
public class Swordsman2 extends Role2{ public void fight(){ System.out.println("挥剑攻击"); } public String toString(){ return "剑士" + super.toString(); } }
-
重新定义时注意:
(1)对于父类中的方法权限,只能扩大不能缩小。
(2)若原来成员
public
,子类中重新定义时不可为private
或protected
(三)再看构造函数
- 创建子类实例后,会先执行父类构造函数定义的流程,再执行子类构造函数定义的流程。
- 父类中可重载多个构造函数,如果子类构造函数中没有指定执行父类中的哪构造函数,默认会调用父类中无参数构造函数。
(四)再看final关键字
- 若
class
前使用了final
关键字定义,表示这个类是最后一个了,不会再有子类,也就是不能被继承。 - 如果打算继承final类,会出现编译错误。
(五)java.lang.Object
- 如果定义类时没有使用extends关键字指定继承任何类,那一定是继承
java.lang.Object
。 - 重新定义
toString()
- 重新定义
equals()
(六)关于垃圾收集
- 无法通过变量引用的对象就是GC认定的垃圾对象。
- 垃圾回收前会调用
finalze()
方法,但由于调用时机无法确定,建议不要使用finalze()方法。
第七章 接口与多态
一、何谓接口
(一)接口定义行为
-
对于“定义行为”,可以用
interface
关键字定义,如下:public interface Swimmer { public abstract void swim(); }
-
接口可以定义行为,但不定义操作,直接标示为
abstract
,且一定是public
,如下:public abstract class Fish implements Swimmer { protected String name; public Fish(String name){ this.name = name; } public String getName(){ return name; } @Override public abstract void swim(); }
-
类要操作接口,必须使用implements关键字。操作某接口时,对接口中定义的方法有两种处理方式:一是操作接口中定义的方法,二是再度将该方法标示为
abstract
public class Human implements Swimmer { private String name; public Human(String name){ this.name = name; } public String getName() { return name; } @Override public void swim(){ System.out.printf("人类 %s 游泳%n",name); } }
-
继承有“是一种”的关系,操作接口则表示“拥有行为”。
(二)行为的多态
- =号右边必须拥有左边的行为,否则就会编译错误。
- 用
Shark shark = (Shark) swimmer
可以忽略逻辑错误,但可能在执行时出错。
(三)解决需求变化
- 类可以操作两个以上的类,也就是拥有两种以上的行为。
- 类可以同时继承某个类,并操作某些接口。
- 接口可以继承自另一个接口,也就是继承父接口行为,再在子接口中额外定义行为。
二、接口语法细节
(一)接口的默认
- 在java中,可使用
interface
来定义抽象的行为与外观,如接口中的方法可声明为public abstract
。 - 可以使用接口枚举常数,,只能定义为
public static final
(为了方便可以省略)。
(二)匿名内部类
在撰写Java程序时,只使用一次的子类或接口操作,不需要定义名称,可以使用匿名内部类来解决
(三)使用enum枚举常数
教材学习中的问题和解决过程
在抄写教材中代码时,我发现教材中有几个代码的名称和代码内是不相符合的,没发现这个问题前,这给我学习教材内容一度带来很大困扰,发现原来是书本问题后,学习才顺利起来
我发现的有问题的代码:P202,P204(最下面),P206
代码调试中的问题和解决过程
问题同上,忘记截图了。。。
在上传代码的时候,我还是喜欢网页直接上传的方式,可惜这样就只能一次性上传了。
其他(感悟、思考等,可选)
这一周的两章任务非常多,再加上院团委的工作,团支书的工作,这一周我几乎是没学其他学科的,只有在课上听的,和做作业的时候临时抱佛脚的一知半解(不管怎样,我还是不愿意抄,只想自己写),下一周的院团委工作会更加重,我不知道自己能否兼顾学习与工作两边,但两边都是我的责任,我都不想放弃,学习中我也不想只学Java,我也想分给其他学科一些预习复习的时间,恳请老师下周布置任务时手下留情!!!
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 3000行 | 15篇 | 300小时 | |
第一周 | 70/70 | 2/2 | 14/14 | |
第二周 | 150/220 | 1/3 | 18/32 | |
第三周 | 400/620 | 1/4 | 35/67 | |
第四周 | 850/1470 | 1/5 | 30/97 |