• 201521123082 《Java程序设计》第5周学习总结


    201521123082 《Java程序设计》第5周学习总结

    标签(空格分隔): java


    1. 本周学习总结

    1.1 尝试使用思维导图总结有关多态与接口的知识点。

    1.2 可选:使用常规方法总结其他上课内容。

    选取上课的PPT中的重点:
    1.接口的语法特性:
    (1)接口不是类,不能使用new进行实例化;
    (2)使用instanceof运算符

      if (anObject instanceofComparable){
      ...}
    

    可以查看该对象是否实现了Comparable接口
    (3)接口可以扩展,将共同的行为抽象到父类接口(例子):

    public interface Moveable{
          void move(double x,double y);
       }
       public interface Powered extends Moveable{
          double milesPerGallon();
          double SPEED_LIMIT = 95;  //public static final
       }
    

    (4)接口中可以包含常量,一个类可以实现多个接口。
    2.Comparable与Comparator区别与联系
    参考下面的题目3
    3.接口与抽象类的区别与联系
    (1)相同之处:都代表系统的抽象层,都不能被实例化,都能包含抽象方法。
    (2)不同之处:可以实现多个接口,但只能继承一个类。
    4.面向接口编程
    参考下面的题目5


    2. 书面作业

    Q1.代码阅读:Child压缩包内源代码

    1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误。并分析输出结果。

    源代码如下:

    package com.parent;
    
    public class Child extends Parent{
        public static void main(String[] args){
            Parent p = new Parent();
            Child c = new Child();
            c.getParenti();
            c.getParentj();
            Other.showParentj(p);
            
        }
        public void getParenti(){
            System.out.println(i);
        }
        public void getParentj(){
            System.out.println(super.j);
            System.out.println(j);
            System.out.println(geti());
            System.out.println(super.geti());
        }
    }
    
    class Other{
        public static void showParentj(Parent p){
            System.out.println(p.j);
            System.out.println(p.geti());
        }
        
    }
    
    class Parent{
        private int i=1;
        protected int j=2;
        protected int geti(){
            return i;
        }
        public void getj(){
            System.out.println(j);
        }
    }
    

    Answer:

    不能通过编译,MyEclipse中出现错误提示:

    改正思路和正确输出结果以及分析:
    父类Parent的i是private类型的,父类的i域对于子类来说是不可见。所以我们将Parent的i定义为protected类型。得到以下输出结果:

    c.getParenti():
    因为子类没有重新定义i,所以输出的值还是父类的i,而父类的i在实例化的时候就初始化为1( protected int i=1;);
    c.getParentj():
    输出的值为父类的j,父类的j,父类的i和父类的i。因为都是在继承父类的方法,j在父类中初始化为2。
    Other.showParentj(p):
    输出的值父类的j和父类的i,方法用static修饰的,所以直接用类名调用。


    1.2 另外一个包中的OutOfParentPackage.java,能否编译通过?提示什么错误?分析原因。如何更改才能使之正常编译?

    import com.parent.*;
    public class OutOfParentPackage{
    	public static void showParentj(Parent p){
    		System.out.println(p.j);
    		System.out.println(p.geti());
    		p.getj();
    	}
    }
    
    Answer:

    如图:

    我们可以看见OutOfParentPackage在parent包外面。
    我们现在MyEclipse中编译出现错误The type Parent is not visible。
    说明Parent类是不可见的。Parent类加上public。
    尝试修改的代码如下:

    public class Parent{
        piblic int i=1;
        protected int j=2;
        public int geti(){
            return i;
        }
        public void getj(){
            System.out.println(j);
        }
    }
    

    使用public使包外的类能够访问。


    1.3 回答:如果为了访问到protected修饰的属性或方法应该怎么办?###

    Answer:

    protected都是不可被继承的,访问protected修饰的属性或方法可以在同一个类中调用protected修饰的属性或方法,也可以同一个包中或是子类中调用protected修饰的属性或方法。


    Q2.abstract进阶:阅读GuessGame抽象类的设计与使用源代码

    package cc.openhome;
    
    import java.util.Scanner;
    //改造前
    public class Guess {
    
    	public static void main(String[] args) {
    
    		Scanner scanner = new Scanner(System.in);
    
    		int number = (int) (Math.random() * 10);
    
    		int guess;
    
    		do {
    
    			System.out.print("猜数字(0 ~ 9):");
    
    			guess = scanner.nextInt();
    		} while (guess != number);
    
    		System.out.println("猜中了...XD");
    	}
    }
    
    //改造后
    
    //Guess2.java
    package cc.openhome;
    
    public class Guess2 {
    
    	public static void main(String[] args) {
    
    		GuessGame game = new ConsoleGame();
    
    		game.go();
    	}
    }
    
    //GuessGame.java
    package cc.openhome;
    
    public abstract class GuessGame {
    
    	public void go() {
    
    		int number = (int) (Math.random() * 10);
    
    		int guess;
    
    		do {
    			print("输入数字:");
    
    			guess = nextInt();
    		} while (guess != number);
    
    		println("猜中了");
    	}
    
    	public abstract void print(String text);
    
    	public abstract void println(String text);
    
    	public abstract int nextInt();
    }
    
    //ConsoleGame.java
    package cc.openhome;
    
    import java.util.Scanner;
    
    public class ConsoleGame extends GuessGame {
    
    	private Scanner scanner = new Scanner(System.in);
    
    	@Override
    	public void print(String text) {
    
    		System.out.print(text);
    	}
    
    	@Override
    	public void println(String text) {
    
    		System.out.println(text);
    	}
    
    	@Override
    	public int nextInt() {
    
    		return scanner.nextInt();
    	}
    
    }
    

    2.1 Guess改造前代码很简单,而改造后的代码使用了抽象类、抽象方法看起来很复杂,那这样的改造到底有什么好处呢?

    Answer:

    好处:

    • 改造前,未使用抽象类,只能控制台输出
    • 改造后,使用抽象类,可以在控制台,也可以使用对话框图形界面等输入

    由java笔记上抽象方法和抽象类的知识点可知:因为我们不知道代码运行的环境,使用抽象方法和抽象类可以先写出代码,后来根据需求和环境续上代码。


    2.2 如果想将该游戏改造成图形界面,应该进行一些什么操作?

    Answer:

    设计一个游戏图形界面类,重写上面的抽象类中的抽象方法满足图形界面的输入输出要求,然后由游戏界面类继承这个抽象类。


    2.3 结合该例子,你觉得什么时候应该使用abstract?

    Answer:

    首先我们先了解什么是抽象类和抽象方法:

    一个抽象类使用关键字abstract来定义,抽象类可以包含抽象方法,当然也可以不包含抽象的方法。抽象类不能被实例化成对象,但是它可以被继承。一个抽象类可能包含有静态属性,也包含有静态方法。当一个抽象类被继承以后,子类通常要实现其父类中的所有的抽象的方法。然而,如果子类没有实现所有的父类中的抽象的方法,那么这个子类也必须被定义成抽象类。
    抽象方法就是不用没有方法体的——也就是没有实现的方法(没有花括号并且后面跟着分号),就像下面这样:
    abstract void sum(int a, int b);

    其次,我觉得以下情况时考虑用抽象类:

    1. 你想要在几个关联紧密的类之间共享代码。
    2. 你想要继承抽象类的那些类有一些公共方法或属性抑或是有修改protected或private属性的权限。这时你也可以考虑使用抽象类。
    3. 你想要声明非静态或者是非最终执行的属性。你可以获得并且修改这些属性所属的对象的状态。

    2.4 重要:在这个例子中,变化的是什么,不变的是什么?尝试结合abstract、继承等概念进行说明。

    Answer:

    我觉得变化的是代码运行环境,比如常见的文本框、控制台、图形界面等;
    不变的是这个抽象类,这个类是通用的,只是根据不同的环境决定不同的输出方式方法。
    说明:
    抽象类(abstract)可能就像是算法,然后我们要运用它的时候,只有通过各种语言,才能在不同的平台上实现其内容。(虽然这么说可能不是那么准确)。其次,我们编写一个抽象类和抽象方法,我们必须有类继承它,这样才有意义,在具体的类中具体实现方法。


    Q3.Comparable与Comparator

    3.1 描述Comparable接口的用途。为什么某个类实现了Comparable接口就可以直接使用Arrays.sort对其进行排序?

    Answer:

    用途:
    此接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序,类的 compareTo 方法被称为它的自然比较方法 。实现此接口的对象列表(和数组)可以通过 Collections.sort ( Arrays.sort进行自动排序。
    分析:
    先贴上JDK查询结果:

    使用Comparable接口,可以让待排序对象所在的类实现Comparable接口,并重写Comparable接口中的compareTo()方法,就可以使用Arrays.sort进行排序。


    3.2 有了Comparable接口为什么还需要Comparator接口呢?

    Answer:

    comparable和Comparator 都是用来实现集合中的排序的,只是Comparable是在集合内部定义的方法实现的排序,Comparator是在集合外部实现的排序。
    所以,如想实现排序,就需要在集合外定义Comparator接口的方法compare()或在集合内实现Comparable接口的方法compareTo() 。
    Comparable是一个对象本身就已经支持自比较所需要实现的接口(如String、Integer自己就可以完成比较大小操作)而Comparator是一个专用的比较器,当这个对象不支持自比较或者自比较函数不能满足你的要求时,你可以写一个比较器来完成两个对象之间大小的比较


    3.3 可选:使用匿名内部类、Lambda表达式实现PTA编程5-2。

    Answer:

    匿名内部类方法:
    直接贴上代码:

    //按name排序
    Comparator<PersonSortable> nameComparator = 
            new Comparator<PersonSortable>(){
                @Override
                public int compare(PersonSortable o1, PersonSortable o2) {
                    return o1.getName().compareTo(o2.getName());
                }
        
    };
    
    //按age排序
    Comparator<PersonSortable> ageComparator = 
            new Comparator<PersonSortable>(){
                @Override
                public int compare(PersonSortable o1, PersonSortable o2) {
                    if (o1.getAge() > o2.getAge()) {
                        return 1;
                    } else if (o1.getAge() < o2.getAge()) {
                        return -1;
                    } else {
                        return 0;
                    }
                }
        
    };
    

    Lambda表达式:
    1.Labmda表达式语法:

    • 参数 -> 表达式或程序块{ }
    • 如果是表达式,则return该表达式的值(无需写return语句)
    • 如果是程序块{ },可以包含多条语句

    2.实现:

    Comparator<PersonSortable> nameComparator = 
            (PersonSortable o1, PersonSortable o2) -> (o1.getName().compareTo(o2.getName()));  
            
    Arrays.sort(personSortables, nameComparator);
    
    Comparator<PersonSortable> ageComparator = 
            (PersonSortable2 o1, PersonSortable2 o2) 
            -> {
                if (o1.getAge() >  o2.getAge()) {
                    return 1;
                } else if (o1.getAge() < o2.getAge()) {
                    return -1;
                } else {
                    return 0;
            }};
            
    Arrays.sort(personSortables, ageComparator);
    

    4.面向接口案例分析

    阅读Case-StudentDao.zip案例

    4.1 画出类关系图,描述每个类与接口的作用。

    Answer:


    Student类:包含名字属性,有参构造器,还有getter/setter和toString()方法。
    StudentDao接口:编写了三个抽象方法,writeStudent、readStudent、diplayAllStudent。
    StudenDaoListImpl类:是对StudentDao接口的操作,存放学生信息采用列表的方式,实现了接口的三个抽象方法,用ArrayList完成操作。
    StudentDaoArrayImpl类:对StudentDao接口的操作,实现接口的三个抽象方法。


    4.2 StudenDaoListImpl与StudentDaoArrayImpl有何区别?

    Answer:

    StudenDaoListImpl是用ArrayList实现的,而StudentDaoArrayImpl是用数组实现的。


    5.什么是面向接口编程?面向接口编程的好处是什么?

    结合题目3与4中的Test.java的代码讨论分析。

    Answer:

    在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的。我们在一般实现一个系统的时候,通常是将定义与实现合为一体,不加分离的,而将所有的定义与实现分离就是面向接口编程吧。

    我是这么理解上面那段话的,就以题目4为例子,体现了接口来实现多态,我们只要Test类里面,我们只要做的就是面向StudentDao接口,确定数据是以何种数据结构来存放,之后往后台写数据,无需考虑后台是什么(到底是数据库、文件、数组、List)。面向接口编程可以将接口与实现相分离,从而大大提高程序的灵活性。
    题目3中,分别调用Comparable和Comparator两个接口,我们可以对我们自己定义的类进行比较,Comparable接口定义一个对象支持自比较,而Comparator接口可以实现比较两个属于某一特定类的专用比较。

    关于面向接口编程可以参考:面向接口编程详解

    6.结对编程:面向对象设计(大作业2-非常重要)

    内容:使用Java代码完成上周做的面向对象设计大作业,需要有初步界面。实现的功能尽量简单,少而精,只包含必要的功能,不要追求高大全。

    写出:类图(尽量精简,不用太多子类,两个即可)、系统常用功能描述、关键代码与界面

    形式: 两人依托码云合作完成。请在这里贴出你们的学号、姓名与任务分工。

    注意: 再过几次课要讲Java图形界面编程,到时候要将该系统升级为图形界面。系统的业务逻辑部分应该变化不大,变化大的是输入与输出部分。所以编码的时候,输入(Scanner)与输出(System.out)的代码,请不要将其与某个业务处理函数绑死。

    选做加分: 给出两人在码云上同一项目的提交记录截图,额外加分。注:两个人在码云上新建一个项目。

    6.1
    学生A[倪兢飞201521123061] 学生B[黄华林201521123082] 项目地址
    http://www.cnblogs.com/JMUNJF/ https://home.cnblogs.com/u/moyi-h/ http://git.oschina.net/smoyi/test
    6.2 常用功能描述框架图

    商讨后功能流程图如下:


    3. 码云上代码提交记录及PTA实验总结

    3.1. 码云代码提交记录

    3.2. PTA实验

    实验5.1:根据题目要求,Arrays.sort不能对自定义对象进行排序,要对自定义的PersonSortable类的对象,使用Arrays.sort进行排序。实现Comparable接口:实现先对name升序排序,如果name相同则对age进行升序排序,由于难度不大,直接关键代码:

     public int compareTo(PersonSortable per) {
            int x = this.name.compareTo(per.name);
            if(x!=0){
                return x;
            }
            else{
                if (this.age>per.age)             
                    return 1;        
                else if(this.age<per.age)
                    return -1;
                else
                    return 0;
            }
        }
    }
    

    实验5.2:题目要求编写不同的Comparator来满足多样的排序需求。难度其实也不大,直接贴上NameComparator类和AgeComparator类的代码:

    class NameComparator implements Comparator {
    
    	@Override
    	public int compare(Object per1, Object per2) {
    		PersonSortable2 p1 = (PersonSortable2) per1;
    		PersonSortable2 p2 = (PersonSortable2) per2;
    		if (p1.getName().compareTo(p2.getName()) > 0)
    			return 1;
    		else if (p1.getName().compareTo(p2.getName()) < 0)
    			return -1;
    		else
    			return 0;
    	}
    }
    
    class AgeComparator implements Comparator {
    
    	@Override
    	public int compare(Object per1, Object per2) {
    
    		PersonSortable2 p1 = (PersonSortable2) per1;
    		PersonSortable2 p2 = (PersonSortable2) per2;
    		if (p1.getAge() > p2.getAge())
    			return 1;
    		else if (p1.getAge() < p2.getAge())
    			return -1;
    		else
    			return 0;
    	}
    }
    

    其实这周的PTA主要是Comparable和Comparator的应用,在上面题目3已经有了较完整的理解表达

  • 相关阅读:
    k8s使用私有镜像仓库
    spark client 配置lzo
    jvm系列(四):jvm调优-命令篇
    mysqldump 备份还原数据库
    df 卡死及ls无法查看文件
    记录一次服务器断电,直接进入救援模式
    nginx开机自启脚本
    mongodb启动关闭脚本
    mongo数据备份恢复
    centos 快速配置网络
  • 原文地址:https://www.cnblogs.com/moyi-h/p/6617925.html
Copyright © 2020-2023  润新知