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

    参考资料

  • 相关阅读:
    PKU JudgeOnline 题目分类
    调试时拼凑带端口的完整网址/域名
    智能电脑监控器,完美解决想监控别人在自己电脑上的一切操作。
    如何清理LDF文件
    使用母版页后FindConttol需要注意
    【外刊IT评论】代码覆盖率:80%,不能少
    推荐2本普通人参悟的书
    处理在母版页加AJAX环境下处理滚动条回发保持不动的问题
    虚拟目录中的web.config不被上级目录的web.config影响的处理
    C++中^符号的意思
  • 原文地址:https://www.cnblogs.com/xzh20145231/p/5324108.html
Copyright © 2020-2023  润新知