20145127《java程序设计》第四周学习总结
教材学习内容总结
第六章 继承与多态
6.1 何为继承
0.面向对象中,子类继承父类,避免城府的行为定义。正确判断使用继承的时机,以及继承之后如何活用多态,才是学习继承时的重点。
1.继承:避免多个类间重复定义共同行为。
继承的好处:将name、level、blood改为其它名称,只要修改Role.java就可以了,只要继承Role的子类都无需修改。
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.pringtf(“剑士:(%s, %d, %d)%n”, swordsMan.getName(), swordMan.getLevel(), swordsMan.getBlood());
}
static void demoMagician()
{
Magician magician = new Magician();
magician.setName("Monica");
magician.getLevel(1);
magician.getBlood(100);
System.out.printf(“魔法师:(&s, &d, &d)%n”, magician.getName(), magician.getLevel(), magician.getBlood());
}
}
执行结果:
剑士:(Justin,1,200)
魔法师:(Monica,1,100)
2.多态与is-a
在java中,子类只能继承一个父类。
is-a:继承除了可避免类间重复的行为定义类外,还有一种重要的关系——is-a,中文称为“是一种”的关系。
多态:抽象的说,就是使用单一接口操作多种类型的对象。
public class RPG {
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.getLevel(1);
magician.getBlood(100);
showBlood(swordsMan);
showBlood(magician);
}
static void showBlood(Role role)
{
System.out.printf("%s 血量 %d%n",role.getName(), role.getBlood());
}
}
执行结果:
Justin 血量 200
Magica 血量 100
3.重新定义行为
再重新定义父类中的某个方法时,子类必须编写与父类方法中相同的签署。
再重新定义某种方法时,加上@override,就不用担心打错字的问题了。
public class RPG {
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.getLevel(1);
magician.getBlood(100);
drawFight(swordsMan);
drawFight(magician);
}
static void showBlood(Role role)
{
System.out.printf(role.getName());
role.fight();
}
}
执行结果:
Justin挥剑攻击
Monica魔法攻击
4.抽象方法、抽象类
java中规定内涵抽象方法的类,一定要在class前标示abstract,表示一个定义不完整的抽象类。(如果尝试用抽象类创建实例,就会引发编译错误)
子类若继承抽象类,对于抽象方法有两种做法:
·继续标示该方法为abstract(该子类因此也是个抽象类,必须在class前标示abstract);
·操作抽象方法。
(两种抽象方法都没有实施,就会引发编译错误)
6.2 继承语法继承
1.protected成员
被声明为protected成员,相同包中的类可以直接存取,不同包中的类可以自己城中的子类直接存取。
java中的权限关键字:public、protected、private。(实际上有4个权限范围,因为没有定义权限关键字,默认就是是包范围)
2.重新定义的细节
对于父类中的方法权限,只能扩大不能缩小。
在JDK5之前,重新定义方法时除了可以定义权限较大的关键字外,其他部分必须与父类中方法签署完全一致。
在JDK5之后,重新定义方法类时,如果返回类型是父类中方法返回类型的子类,也是可以通过编译的。
3.java.lang.Object
如果定义类时没有使用extends关键字指定继承任何类,那一定是继承java.lang.Object。
因此在java中,任何类追溯至最上层一定就是java.lang.Object,也就是说,在java中所有对象,一定“是一种”Object。
任何类型的对象,都可以使用Object申明的名称来参考。
import java.util.Scanner;
import static java.lang.System.out;
public class Guess
{
public static void main(String[] args)
{
ArrayList names = new ArrayList();
collectNameTo(names);
out.printIn(“访客名单:”);
printUpperCase(names);
}
static void collectNameTo(ArrayList names)
{
Scanner console = new Scanner(System.in);
while(true)
{
out.print(“访客名称:”);
String names = console.nextLine();
if(name.equals("quit"))
{
break;
}
names.add(name);
}
}
static void printUpperCase(ArrayList names)
{
for(int i = 0; i < names.size(); i++)
{
String name = (String) names.get(i);
out.printIn(name.toUpperCase());
}
}
}
执行结果:
访客名称:Justin
访客名称:Monica
访客名称:Irene
访客名称:quit
访客名单:
JUSTIN
MONICA
IRENE
4.关于垃圾收集
创建对象会占据内存,如果程序执行流程中已经无法再使用某个对象,该对象只是徒耗内存的莱基。
对于不再使用的对象,JVM有垃圾收集机制(GC),收集到的垃圾对象所占据的内存,会被垃圾收集器释放。
5.再看抽象类
第七章 接口与多态
1.接口定义行为
类要操作接口,必须使用implemente关键字。
2.行为的多态
public class Ocean{
public static void main(String[] args)
{
doSwim(new Anemonefish("尼莫"));
doSwim(new Shark("兰尼"));
doSwim(new Huamn("贾斯汀"));
doSwim(new Submarine("黄色一号"));
}
static void doSwim(Swimmer swimmer){
swimmer.swim();
}
}
执行结果:
小丑鱼 尼莫 游泳
鲨鱼 兰尼 游泳
人类 贾斯汀 游泳
潜水艇 黄色一号 潜行
7.2 接口语法细节
1.接口的默认
在java中,可使用interface来定义抽象行为与外观(如接口中的方法可声明为public abstract)。接口中的方法没有操作时,一定得是公开且抽象。可以省略public abstract,编译程序会自动帮你加上public abstract。默认一定是public。
2.匿名内部类
在编写java程序时,经常会有临时继承某个类或操作某个接口并建立实例的需求。由于这类子类或接口操作类只使用一次,不需要为这些类定义名称,这时可以使用匿名内部类(AIC)来解决这个需求。
new 父类()|接口(){
//类本体操作
};
使用匿名内部类,直接建立操作ClientListener的对象:
public class MultiChat{
public static void main(String[] args){
Client c1 = new Clent("127.0.0.1","Caterpillar");
Client c2 = new Clent("192.168.0.2","Justin");
ClientQueue queue = new ClientQueue();
queue.addClientListener(new ClientListener(){
@Override
public void clientAdded(ClientEvent event){
System.out.printf("%s 从 %s 联机%n", event.getName(), event.getIp());
}
@Override
public void clientRemoved(ClientEvent event){
System.out.printf("%s 从 %s 联机%n", event.getName(), event.getIp());
}
});
queue.add(c1);
queue.add(c2);
queue.remove(c1);
queue.remove(c2);
}
}
执行结果:
caterpillar 从 127.0.0.1 联机
justin 从 192.168.0.2 联机
caterpillar 从 127.0.0.1 联机
justin 从 192.168.0.2 联机
3.使用enum枚举常数
从JDK5之后新增了enum语法,可用于定义枚举常数。
例
public enum Action{
STOP, RIGHT, LEFT, UP, DOWN
}
范例中的enum定义的Action实际上是个类,而enum中例举的STOP, RIGHT, LEFT, UP, DOWN常数,实际上是public static final,且为Action实例。你无法编写程序直接实例化Action,因为构造函数权限设定为private,只有Action类中才可以实例化。
教材学习中的问题和解决过程
本周的学习内容和上周一样太多,光是看书并不能都看懂弄会,并且只是自己敲代码还是有许多的不理解,这两章的内容都有些抽象,所以许多地方都询问了同学。
代码调试中的问题和解决过程
第六章两个章节都有关于抽象方法、抽象类的内容,但是很难理解,光看书上的代码并没有搞懂。
其他(感悟、思考等)
说实话大量时间放在java上,但是感觉学习的效果并不是很理想,看来我还是得好好想想学习方法是否哪里不对。
参考资料
Java学习笔记(第8版)
《Java学习笔记(第8版)》学习指导