20145231第四周学习笔记
20145231 《Java程序设计》第4周学习总结
教材学习内容总结
基本概念:
•何谓继承
继承:面向对象中,子类继承父类,避免重复定义的共同行为;
extends关键字:在继承父类的程序代码基础上,补充定义新的程序代码,扩充其原本没有的行为;
继承的好处:避免重复的同时,若是要对相应的数据成员名称做修改,只需要在父类中修改即可;
•多态与is-a
is-a关系:子类只能继承一个父类,即子类“是一种”父类,可用来判断如下代码片段:
Role role1 = new Swordsman();
Swordsman swordsman = new Role();
用is-a关系判断是否能编译通过即右边类是不是左边类的子类;
多态:使用单一接口操作多种类型对象,不需要用重载的方式写很多个方法,具有更高的维护性;
•重新定义行为
重新定义:在继承父类之后,定义与父类中相同的方法部署,但执行内容不同;在重新定义父类中某个方法时,子类必须撰写与父类方法中相同的签署;
•抽象方法抽象类
abstract关键字:在某方法区块中没有任何程序代码操作时,使用abstract标示该方法为抽象方法(该方法不用撰写{}区块,直接;结束即可);
带有abstract关键字的类为定义不完整的抽象类,不能创建实例;
继承抽象类:1、继续标示该方法为abstract;2、操作抽象方法;否则编译报错;
•继承语法细节
protected成员:被声明为protected的成员,相同包中的类可以直接存取,不同包中的类可以在继承后的子类直接存取;
重新定义的细节:重新定义方法时,若只是希望在父类中方法前后做点加工,可在父类中直接添加,想取得父类中的方法定义,只需在调用前加上super关键字;(使用super关键字调用的父类方法不能定义为private,同时,重新定义方法时,对于父类中的方法权限只能扩大不能缩小)
JDK5之后,如果返回类型是父类中方法返回类型的子类,可通过编译;
构造函数:如果子类构造函数中没有指定调用父类中那个构造函数,默认会调用父类中无参数构造函数;
final关键字:class前使用final,表示这是最后一个类不会再有子类;定义方法为final表示最后一次定义方法;
java.lang.Object:定义类时若没有extends关键字,那一定是继承java.lang.Object;(顶层父类,Object上定义的方法所有对象都继承下来了,只要没有定义为final,都可以重新定义)
tostring()、equals()都是Object类定义的方法,返回值类型分别为字符串型和布尔型;
instanceof运算符:判断对象是否由某个类创建,左操作数是对象,右操作数是类,只要左操作数是右操作数的子类型,返回结果就为true;
垃圾收集:程序执行流程中无法再使用某个对象,该对象就是徒耗内存的垃圾,就会被回收;
•何谓接口
接口:可用于定义行为但不操作(表示拥有行为,是多重继承的一种方式),类要操作接口,就必须有implements关键字(为了生成与特定接口相符合的类);
接口中定义的方法的处理方式:操作接口中定义的方法、再度将其标示为abstract;
•接口的语法细节
接口的默认:接口中的方法没有操作时,一定得是公开且抽象(interface关键字:定义抽象行为与外观);
枚举常数:为了在维护程序时使程序清晰;
匿名内部类:对于只使用一次的继承某个类的子类或接口操作类,不需为这些类定义名称;
教材学习中的问题和解决过程
问题一:private成员不能被继承?
解决过程:private成员会被继承,只不过子类无法直接存取,必须通过父类提出的访问方法来存取;
问题二:如何判断一段程序是否是合法的多态语法?
Swimmer swimmer = new Shark();
Swimmer swimmer = new Human();
Swimmer swimmer = new Submarine();\\编译通过
解决过程:判断右边是否拥有左边的行为,即右边对象是否操作了左边接口;
Shark shark = swimmer;\\编译失败
因为有Swimmer行为的不一定是shark实例,此时需要加上扮演语法:
Shark shark = (Shark) swimmer;
即执行时参考shark实例,让其扮演shark(实际参考对象与扮演对象要一致,否则报错);
问题三:类可以操作两个以上的接口,如果有两个接口。都定义了某方法,操作两个接口的类会怎样?
interface Action{
void execute();
}
interface Some extends Action{
void doSome();
}
interface Other extends Action{
void doOther();
}
public class Service implements Some,Other{
@Override
public void execute(){
System.out.println("execute()");
}
@Override
public void doSome(){
System.out.println("doSome()");
}
@Override
public void doOther(){
System.out.println("doOther()");
}
}
解决过程:以上代码在编译时可以通过,但是应该思考不同接口定义的方法是否表示不同行为,若表示不同行为,那么类在操作时,应该有不同的方法操作,,相对应的方法名称就要不同,这样类在操作时才可以有两个不同的方法操作;如果表示相同的行为,可以通过定义一个父接口,在当中定义该方法,而其他两个接口继承该接口,各自定义自己的doSome(),doOther()方法;
问题四:enum定义枚举常数到底是怎么回事?
public final class Action extends Enum{
...
private Action(String s,int i){
super(s,i);
}
public static final Action STOP;
public static final Action RIGHT;
public static final Action LEFT;
public static final Action UP;
public static final Action DOWN;
...
static{
STOP = new Action("STOP",0);
RIGHT = new Action("RIGHT",1);
LEFT = new Action("LEFT",2);
UP = new Action("UP"3);
DOWN = new Action("DOWN",4);
...
}
}\\Enum枚举常数的部分细节
import static java.lang.System.out
public class Game {
public static void main(String[] args) {
play(Action.RIGHT);
play(Action.UP);
}
public static void play(Action action) {
switch(action){
case STOP:
out.println("播放停止动画");
break;
case RIGHT:
out.println("播放向右动画");
break;
case LEFT:
out.println("播放向左动画");
break;
case UP:
out.println("播放向上动画");
break;
case DOWN:
out.println("播放向下动画");
break;
}
}
}\\使用Action类的例子
解决过程:enum定义了特殊的类,继承自java.lang.Enum,由编译程序自己处理,enum中列举的常数,实际上是public static final,且为枚举类型实例,无法撰写程序直接实例化枚举类型,因为构造函数权限设定为private,只有类中才可以实例化。
代码调试中的问题和解决过程
接口定义行为:
public interface Swimmer{
public abstract void swim();
}
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();
}
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);
}
}
public class Submarine implements Swimmer {
private String name;
public Submarine(String name){
this.name = name;
}
public String getName(){
return name;
}
@Override
public void swim(){
System.out.printf("潜水艇 %s 潜行%n",name);
}
}
行为的多态:
public class Ocean {
public static void main(String[] args) {
doSwim(new Anemonfish("尼莫"));
doSwim(new Shark("兰尼"));
doSwim(new Human("贾斯丁"));
}
static void doSwim(Swimmer swimmer){
swimmer.swim();
}
}
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");
}
}
public class FlyingFish extends Fish implements Flyer {
public FlyingFish(String name){
super(name);
}
@Override
public void swim(){
System.out.printf("飞鱼游泳");
}
@Override
public void fly(){
System.out.println("飞鱼会飞");
}
}
public class Swimplayer extends Human implements Swimmer {
public Swimplayer(String name)
{
super(name);
}
@Override
public void swim() {
System.out.printf("游泳选手 %s 游泳%n", name);
}
}\\其中要修改之前定义的Human类的字符串变量name的权限为protected
public class Airplane implements Flyer {
protected String name;
public Airplane(String name){
this.name = name;
}
@Override
public void fly(){
System.out.printf("飞机 %s 在飞%n",name);
}
}
public class Seaplane extends Airplane implements Swimmer {
private String name;
{
super(name);
}
@Override
public void fly(){
System.out.print("海上");
super.fly();
}
@Override
public void swim(){
System.out.printf("海上飞机 %s 航行海面%n",name);
}
}
public Helicopter(String name){
super(name);
}
@Override
public void fly(){
System.out.printf("飞机 %s 在飞%n",name);
}
}
public class Boat implements Swimmer {
protected String name;
public Boat(String name){
this.name = name;
}
@Override
public void swim(){
System.out.printf("船在水面 %s 航行%n",name);
}
}\\继承父接口行为
接口的默认:
public interface Action{
public static final int STOP = 0;
public static final int RIGHT = 1;
public static final int LEFT = 2;
public static final int UP = 3;
public static final int DOWN = 4;
}
import static java.lang.System.out;
public class Game2 {
public static void main(String[] args) {
play(Action.RIGHT);
play(Action.UP);
}
public static void play(int action){
switch(action){
case Action.STOP:
out.println("播放停止动画");
break;
case Action.RIGHT:
out.println("播放向右动画");
break;
case Action.LEFT:
out.println("播放向左动画");
break;
case Action.UP:
out.println("播放向上动画");
break;
case Action.DOWN:
out.println("播放向下动画");
break;
default:
out.println("不支持此动作");
}
}
}
关于使用匿名内部类的实例:
public class Client {
public final String ip;
public final String name;
public Client(String ip,String name){
this.ip = ip;
this.name = name;
}
}
public class ClientEvent {
private Client client;
public ClientEvent(Client client){
this.client = client;
}
public String getName(){
return client.name;
}
public String getIp(){
return client.ip;
}
}
public interface ClientListner{
void clientAdd(ClientEvent event);
void clientAdd(ClientEvent event);
}
public class MultiChat {
public static void main(String[] args) {
Client c1= new Client("127.0.0.1","Caterpillar");
Client c2= new Client("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);
}
}
import java.util.ArrayList
public class ClientQueue {
private ArrayList clients = new ArrayList();
private ArrayList listeners = new ArrayList();
public void addClientListener(ClientListner listener){
listeners.add(listener);
}
public void add(Client client){
clients.add(client);
ClientEvent event = new ClientEvent(client);
for(int i = 0;i<listeners.size();i++){
ClientListner listner = (ClientListner) listeners.get(i);
listner.clientAdded(event);
}
}
public void remove(Client client){
clients.remove(client);
ClientEvent event = new ClientEvent(client);
for(int i = 0;i<listeners.size();i++){
ClientListner listner = (ClientListner)listeners.get(i);
listner.clientremoved(event);
}
}
}
以上均为可运行代码,不作运行结果赘述。
本周代码托管截图
其他(感悟、思考等,可选)
在本周的学习过程中,产生了很多的疑问,通过不断翻看已经学习过的章节复习回顾以加强对新知识的理解,同时我觉得本书最大的一个优点是,在提出每一个新的概念之前都会举一个较为具体的例子,附有代码,列出其不足之处,基于改进的基础上提出新内容,继承、多态、接口的提出都如此,通过敲代码,就能感受到区别以及后者的优势,但是遇到最大的问题也出现在这些代码上,片段式的代码,在一些语法细节上不便于理解,调试时也出现很多问题,不知道完整的代码形式,只能凭着对前面几章的理解自己尝试,在此过程中发现了之前自己理解上的一些偏差,加深了对概念的认识,也算是本周的一个收获吧。继续加油,路漫漫其修远兮,吾将上下而求索。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 200/200 | 2/2 | 20/20 | |
第二周 | 300/500 | 2/4 | 21/41 | |
第三周 | 450/950 | 3/7 | 20/61 | |
第四周 | 443/1393 | 2/9 | 22/83 | 了解了接口与继承的区别及运用继承、接口、多态方式编程的好处 |