zoukankan      html  css  js  c++  java
  • 201521123005《java程序设计》第五周学习总结

    1. 本周学习总结

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

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

    • 接口
      有点类似继承中父类与子类的关系
      方法声明和常量值的集合
      对行为的抽象
      一种特殊的抽象类
    • Comparable接口
      实现了Comparable接口的类都有一个(has-a) compareTo方法
      Arrays.sort:数组中的所有元素都必须实现 Comparable 接口
    • Comparator接口
      Arrays.sort使用了Comparator接口
    • 接口与多态
      拥有同样的方法声明(哪个方法),但这个方法各有不同实现
    • 实现接口还是使用继承
      接口体现了一种has-a关系
      继承体现了一种is-a关系

    2. 书面作业

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

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

    package parent;
    
    public class OutOfParentPackage{
    	public static void showParentj(Parent p){
    		System.out.println(p.j);
    		System.out.println(p.geti());
    		p.getj();
    	}
    }
    class Parent{
        private int i=1;
        protected int j=2;
        protected int geti(){
            return i;
        }
        public void getj(){
            System.out.println(j);
        }
    }
    class Other{
        public static void showParentj(Parent p){
            System.out.println(p.j);
            System.out.println(p.geti());
        }
        
    }
    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());
        }
    }
    
    可能直接看一下子无法看出错误在哪,这个时候就要借助eclipse来帮我们快速找到错误。用eclipse运行一下编译错误的原因如下图
    

    从图中可以看出出错的语句是`System.out.println(i);`。提示错误是the field Parent.i is not visible。原因是Parent类中的i是私有类型,在外部不能访问。因为Parent中有geti()的方法,所以我们直接i改成geti();即 `System.out.println(geti());` 。
    

    改完运行一下,输出结果为:

    分析输出结果:因为Child类中没有属性i或者说没有重新定义i,所以`c.getParenti();`是要输出父类Parent的i。而父类的i一开始就初始化为1,所以输出1。
    同理`c.getParentj();`输出父类的j,且父类的j一开始就初始化为2,所以输出2。`Other.showParentj(p);`输出父类的i和j,且被static关键字修饰的方法不需要依赖
    于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。
    

    1.2 另外一个包中的OutOfParentPackage.java,能否编译通过?提示什么错误?分析原因。如何更改才能使之正常编译?(写不出来正确答案不要紧,但请一定写出思考过程)
    OutOfParentPackage.java的代码:

    package parent2;
    public class OutOfParentPackage{
    	public static void showParentj(Parent p){
    		System.out.println(p.j);
    		System.out.println(p.geti());
    		p.getj();
    	}
    }
    

    用eclipse运行一下编译错误的原因如下图

    提示错误是The type Parent is not visible。Parent类是不可见的。因为OutOfParentPackage.java在parent包之外,Parent类的访问权限没有写,默认是包访问权限,所以访问不到。按照提示,把Parent类前面加上指定词public。结果还是编译错误
    




    第一句错误是j不能直接访问j,因为它是用protected修饰的,不能通过包外部去访问。根据提示把Parent类中的方法geti()的访问权限改成public。
    第二句错误是geti()方法是用protected来修饰的,所以也是访问不到的。根据提示把Parent类中的方法getj()的访问权限改成public。

    代码如下:

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

    然后就编译成功运行一下

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

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

    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");
        }
    }
    
    

    改造后的代码:

    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();
    }
    
    改造前,未使用抽象类,只能控制台输出
    
    改造后,使用抽象类,可以在控制台,也可以使用对话框图形界面等输入
    

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

    答:设计一个图形界面猜数字的类去继承Guess中的抽象类,然后用图形界面支持的输入输出语句来重写抽象类当中的抽象方法。
    

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

    答:抽象类使用abstract关键字修饰,包含抽象方法。某个父类只是知道其子类应该包含怎样的方法,但无法准确知道这些子类如何实现这些方法用到abstract,只有声明而没有方法体,抽象方法正是这样的一个方法。上例中是具体的方法还未完成,在我不清楚具体是什么方法,又需要用到这个方法来完成其他代码时,这时就要用到抽象方法。这种抽象方法可以被不同的类以不同的方式去操纵,感觉有点像多态。
        
    

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

    答:在这个例子中,变化的是输入的方法,可以采用不同的方法输入,如从控制台输入、从对话框图形界面输入等等。不变的是抽象方法,它可以使用不同方法的输入、输出,完成一个猜数的游戏。我们根据需求的不同来具体决定到底使用何种输入输出方法。这个类是抽象的,即没有具体的输入、输出的的方法这个游戏就没有办法进行。所以我们要有具体的方法来实现,而具体的实现要通过继承来完成。因为抽象类的抽象方法是没有具体定义的,也就是说一个抽象类,没有别的类去继承它,就很没有意义。所以我们要有一个不是抽象类去实现抽象类的抽象方法。这个实现的过程就是继承,继承抽象类的方法,然后通过复写的形式来具体实现方法的细节。
    

    Q3.Comparable与Comparator

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

        答:Comparable接口将比较代码嵌入自身类中。在开发中我们可能会遇到需要将一些对象有序的放入到集合中,这时候我们只需要让类实现java.lang.Comparable<T>接
             口。因为Comparable接口只有`public int compareTo(T o);`一个方法,所以覆盖compareTo这个方法即可实现自动排序,这样就不用自己写一个排序的方法。
    ``` 
    
    ![](http://images2015.cnblogs.com/blog/1109893/201703/1109893-20170323190644877-1252247517.png)
    
        先看一下Arrays.sort如何进行排序
    
    ![](http://images2015.cnblogs.com/blog/1109893/201703/1109893-20170323192211627-229090398.png)
    
        从截图可以知道Arrays.sort的算法使用到了Comparable,也就是说要转化成Comparable才能正确使用该方法。然而如果一个类并没有去操作Comparable接口,它就不能被
        正确的使用。
    
    3.2 有了Comparable接口为什么还需要Comparator接口呢?
    

    答:因为有时候我们比较不止只有一个属性。比如我们买东西当两个东西价格相同时,我们就要比较一下它们的外观,哪个好看买哪个,此时就不能用Comparable接口来进行比较。Comparable接口是一个内比较器,在类内部定义了一种比较方式。Comparator接口在一个独立的类中实现比较。Comparable接口强制进行自然排序,而Comparator接口不强制进行自然排序,可以指定排序顺序。

    
    ###**Q4面向接口案例分析**
    阅读Case-StudentDao.zip案例
    4.1 画出类关系图,描述每个类与接口的作用。
    ![](http://images2015.cnblogs.com/blog/1109893/201703/1109893-20170325210333080-47960196.png)
    
    
    

    Student类:属性只有String name;方法有:getName()、setName()、toString()和构造函数,是StudentDaoArrayImpl类和StudenDaoListImpl类的父类。
    StudentDaoArrayImpl类:用数组来存放学生信息,有构造函数,具体实现StudentDao接口的三个抽象方法。用Array的具体方法来完成相应操作。
    readStudent(String) 读取学生信息,如果找不到返回null。
    diplayAllStudent()遍历整个数组,没找到学生信息返回false,对象为非空则输出学生信息。
    writeStudent(Student )添加学生信息,添加成功返回true。
    StudenDaoListImpl类:用列表来存放学生信息,有构造函数,具体实现StudentDao接口的三个抽象方法。用ArrayList的具体方法来完成相应操作。
    StudentDao接口:提供三个抽象方法,写入学生数据、读取学生数据和显示所有学生信息。

    4.2 StudenDaoListImpl与StudentDaoArrayImpl有何区别?
    
    

    答:StudenDaoListImpl与StudentDaoArrayImpl各自的私有属性不同,即实现的数据结构不一样,StudenDaoListImpl是用ArrayList实现的,而StudentDaoArrayImpl是用数组实现的。所以两个类对于接口的抽象方法,就会有不同的实现。两个类具体的方法不同。

    ###**Q5.什么是面向接口编程?面向接口编程的好处是什么?结合题目3与4(Test.java的代码)讨论分析。**
    >在系统分析和架构中,分清层次和依赖关系,每个层次不是直接向其上层提供服务(即不是直接实例化在上层中),而是通过定义一组接口,仅向上层暴露其接口功能,上层
     对于下层仅仅是接口依赖,而不依赖具体类。
    
    

    答:面向接口编程关注的是不同的类是否有共同的方法,不关心对象本身。
    题目3用到Comparable和Comparator两个接口,通过这两个接口,我们可以很方便地对自己定义的类进行比较,从而调用Arrays里面已经写好的sort()方法来排序。这个过程相当于面向接口编程。题目4也是如此,在Test类里面,我们只要关心数据到底是以何种数据结构来存放,不需要管具体的底层实现。用列表,数组都可以实现写入学生数据、读取学生数据和遍历学生信息的操作。这样一来就很方便,就如计算机的USB接口,不管是要接U盘还是手机类的外设,只关心接口一致就可以,至于内容就不管。这样就无须知道对象是用什么类来实现的,只须知道定义接口的抽象类。

    ###**Q6结对编程:面向对象设计(大作业2-非常重要)**
    内容:使用Java代码完成上周做的面向对象设计大作业,需要有初步界面。实现的功能尽量简单,少而精,只包含必要的功能,不要追求高大全。
    写出:类图(尽量精简,不用太多子类)、系统常用功能描述、关键代码与界面
    形式: 两人依托码云合作完成。请在这里贴出你们的学号、姓名与任务分工。
    注意: 再过几次课要讲Java图形界面编程,到时候要将该系统升级为图形界面。系统的业务逻辑部分应该变化不大,变化大的是输入与输出部分。所以编码的时候,输入(Scanner)与输出(System.out)的代码,请不要将其与某个业务处理函数绑死。
    选做加分: 给出两人在码云上同一项目的提交记录截图,额外加分。注:两个人在码云上新建一个项目。
    结对编程参考资料
    
    6.1
    
    |杨雪莹|董美凤|项目地址|
    |:----:|:----:|:----:|
    |http://www.cnblogs.com/yangxy/p/6591309.html|http://www.cnblogs.com/dongmf/|https://git.oschina.net/yangxueying/shopping.git|
    
    ![](http://images2015.cnblogs.com/blog/1109893/201703/1109893-20170325203037565-2101196801.png)
    
    
    6.2常用功能描述框架图
    ![](http://images2015.cnblogs.com/blog/1109893/201703/1109893-20170325202521643-439674524.png)
    
    
    
    
    6.3 关键代码
    

    class Product {
    public String name;
    public double price;
    public int num;

    public Product(String name, double price, int num) {
    	super();
    	this.name = name;
    	this.price = price;
    	this.num = num;
    }
    public double getPrice() {
    	return price;
    }
    public void setPrice(double price) {
    	this.price = price;
    }
    public int getNum() {
    	return num;
    }
    public void setNum(int num) {
    	this.num = num;
    }
    public String getName() {
    	return name;
    }
    public void setName(String name) {
    	this.name = name;
    }
    @Override
    public String toString() {
    	return "Product [price=" + price + ", num=" + num + ", name=" + name + "]";
    }
    
    }
    

    class Book extends Product{
    private String author;
    private String isbn;
    public String getAuthor() {
    return author;
    }
    public void setAuthor(String author) {
    this.author = author;
    }
    public String getIsbn() {
    return isbn;
    }
    public void setIsbn(String isbn) {
    this.isbn = isbn;
    }

    public Book(String name, double price, int num, String author, String isbn) {
    	super(name, price, num);
    	this.author = author;
    	this.isbn = isbn;
    }
    
    
    @Override
    public String toString() {
    	return "书名:" + name +",作者:" + author + ", ISBN:" + isbn + ",价格:" + price
    			+ ",库存:" + num ;
    }
    

    }

    6.4 运行界面
    ![](http://images2015.cnblogs.com/blog/1109893/201703/1109893-20170325013849471-139830045.png)
    
    
    ##**3. 码云上代码提交记录及PTA实验总结**
    ![](http://images2015.cnblogs.com/blog/1109893/201703/1109893-20170325012326908-184182605.png)
    
    
    题目集:jmu-Java-04-面向对象2-进阶-多态接口内部类
    
    3.1. 码云代码提交记录
    在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图
    
    3.2. PTA实验
       实验总结:
    

    5-1:这题主要问题是实现Comparable接口,实现先对name升序排序,如果name相同则对age进行升序排序。因为要用Arrays.sort进行排序,所以要有覆盖
    compareTo()的方法,即要自己定义比较函数,如下:
    public int compareTo(PersonSortable s) {
    int num = new String (this.name).compareTo(new String (s.name));//按姓名从小到大进行排序
    if(num == 0){
    //如果姓名相同,再年龄比较,
    return new Integer(this.getAge()).compareTo(new Integer(s.getAge()));
    }
    return num;
    }
    }
    5-2:这题需要不同的方法实现排序,即编写NameComparator类,实现对name进行升序排序,编写AgeComparator类,对age进行升序排序。Arrays.sort可以对所有
    实现Comparable的对象进行排序。但如果有多种排序需求,如有时候需对name进行降序排序,有时候只需要对年龄进行排序。使用Comparable无法满足这样
    的需求。所以可以编写不同的Comparator来满足多样的排序需求。具体方法如下:
    class NameComparator implements Comparator
    {
    @Override
    public int compare(PersonSortable2 o1, PersonSortable2 o2) {
    // TODO Auto-generated method stub
    return new String (o1.getName()).compareTo(o2.getName());
    }

        }
        class AgeComparator implements Comparator<PersonSortable2>
        {
            @Override
            public int compare(PersonSortable2 o1, PersonSortable2 o2) {
    	        // TODO Auto-generated method stub
    	        return o1.getAge()-o2.getAge();
            }
    
        }
       写两个不同的排序方法且都implement Comparator接口,就可以实现不同排序方法。
    
  • 相关阅读:
    Android源码分析(二)-----如何编译修改后的framework资源文件
    Android源码分析(一)-----如何快速掌握Android编译文件
    AI2(App Inventor 2)离线版服务器网络版
    AI2(App Inventor 2)离线版服务器单机版
    AI2(App Inventor 2)离线版服务器(2019.04.28更新)
    解释器模式
    迭代器模式
    备忘录模式
    访问者模式
    命令模式
  • 原文地址:https://www.cnblogs.com/yangxy/p/6591309.html
Copyright © 2011-2022 走看看