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 了解了接口与继承的区别及运用继承、接口、多态方式编程的好处

参考资料

原文地址:https://www.cnblogs.com/xzh20145231/p/5324108.html