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

1. 本章学习总结

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

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

  • 接口:不是类,不能使用new实例化,可用instanceof判断是否实现某接口。接口的扩展可通过继承
  • Arrays.sort实现对指定的对象数组进行升序,所有元素都必须实现Comparable(也可以用Collections.sort)。
  • 面向接口编程:将代码与接口相联系,但是编写不需要考虑有什么类实现了该接口。只要一旦有类实现该接口,直接用这个接口代码实现就行。例如if (((Comparable)dest[i-1]).compareTo(dest[i]) > 0)可用于实现了Comparable接口的任何类。
  • 内部类:即在一个类里面再写另外一个类,static class称为静态内部类(又称嵌套类)。匿名内部类,没有名字的类,格式为:new 类名(){};或new 接口<>(){};

2. 书面作业

Q1.代码阅读:Child压缩包内源代码
 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误。并分析输出结果。

package com.parent;
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());
    }
}

  

  • 上图可知道,i被private修饰,是不可见的,所以在子类中无法访问。改为protected修饰就可以在本类及其子类进行访问了。
  • 接着,c.getParenti();因为在Child中没有重新定义i,所以访问的是父类的i=1,c.getParentj();因为在Child中没有重新定义geti()和j,所以都是访问父类的geti()和j。而Other.showParentj(p);因为被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();
	}
}

  

  • 由上图可知,Parent类是不可见的,因为OutOfParentPackage.java不在Parent包内,所以按照提示可在Parent类加上public修饰,但是仍然会显示如下错误:
      
      
  • 所以按照提示再将protected int j=2;protected int geti(){}改为public int j=2;public int geti(),因为protected只能让本类及其子类访问。这样就可以运行出1.1题目的输出结果了。
     
    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");
    }
}
//改造后
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.1 Guess改造前代码很简单,而改造后的代码使用了抽象类、抽象方法看起来很复杂,那这样的改造到底有什么好处呢?

  • 引用文件名的提示

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

  • 使用抽象类、抽象方法不用给出具体的实现,本题将输入和输出方法抽象出来,给出了一个输入输出的框架,当你具体想使用控制台、对话框图形界面进行输入时,只需要重写它即可,而不用反复的创建适用于控制台、对话框图形界面的输入输出方法,省去了写很多的代码,实现了代码的可扩展性。
  • 举个例子:做一个游戏的时候,当你要创建一个角色的时候,反复的创建类和方法会很麻烦,产生大量的代码冗余,因为一个角色可能有很多职业、技能,但是如果创建一个抽象类的话,可以让创建的角色继承抽象类中的属性和方法,然后在调用重写方法,这样就可以省去写很多代码。所以抽象类就像一个模板,很方便后期的调用和重写,实现了程序的可扩展性。

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

  • 首先需要有个框架,让GuessFrame继承JFrame框架类,然后让图形界面支持的输入输出重写抽象方法的输入输出,添加界面组件,(Java为GUI提供的对象都在import javax.swing.;import java.awt.;包中)

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

  • abstract修饰的类叫做抽象类,它不能被实例化,只能被子类继承并且重写其抽象方法;abstract修饰的方法叫做抽象方法,它不能有具体的实现,只能做声明,只能在子类中被重写。
  • 当不知道具体实现方法的时候,可以使用abstract。Guess这个例子,可以看出抽象出输入输出方法以方便去后期的调用是要用作控制台、对话框图形界面等输入输出。建立了一个框架(模板)以方便后期使用。
  • 或者是之前的abstract Shape类,Circle类和Rectangle类都有getArea方法,你可以先将getArea方法抽象出来,在后面在重写它。

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

  • 变化的是使用的环境,也就是我们要用控制台、对话框图形界面还是其他环境进行输入输出,不变的是Guess抽象类。Guess抽象类可以在任何环境下通用相当于一个模板,但是因为它是abstract修饰的,它只有声明而没有具体的实现,如果想用它,你就必须继承它并且重写它的抽象方法才能具体的实现。

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

  • Comparable接口是一个排序接口,如果一个类实现了Comparable接口,那么代表它本身支持排序,它实现的是对类的每个对象进行整体排序。Arrays类中的sort方法可以对对象数组进行升序排序,但是必须对象所属的类必须实现Comparable接口。由下图可知:对象数组被强制转成Comparable
      

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

  • Comparable接口将比较代码嵌套进自身类,相当于内部比较器;而Comparator接口在一个独立的类中实现比较。由3.1可知实现Comparable接口,得该类本身支持排序,只支持按照一种规则排序,而Comparator接口,如果我们需要对类进行某种排序而该类本身不具有这种排序,则可以通过建立一个Comparator比较器来进行排序,并且它支持按照多种规则进行排序。

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

  • 匿名内部类
Arrays.sort(str, new Comparator<PersonSortable2>(){
			public int compare(PersonSortable2 o1, PersonSortable2 o2) {
				return o1.getName().compareTo(o2.getName());
			}
		});
Arrays.sort(str, new Comparator<PersonSortable2>(){
			public int compare(PersonSortable2 o1, PersonSortable2 o2) {
				return Integer.toString(o1.getAge()).compareTo(Integer.toString(o2.getAge()));
			}
		});
  • Lambda表达式
Arrays.sort(str, (PersonSortable2 o1, PersonSortable2 o2) 
				->(o1.getName().compareTo(o2.getName())));
			}
Arrays.sort(str, (PersonSortable2 o1, PersonSortable2 o2)
		       ->(Integer.toString(o1.getAge()).compareTo(Integer.toString(o2.getAge())));
			}

Q4.面向接口案例分析 阅读Case-StudentDao.zip案例
 4.1 画出类关系图,描述每个类与接口的作用。

  • 由下图可知StudenDaoListImpl、StudentDaoArrayImpl实现StudentDao接口,继承自Student。
      

 4.2 StudenDaoListImpl与StudentDaoArrayImpl有何区别?

  • StudenDaoListImpl的属性是ArrayList(不规则数组),而StrudentArrayImpl(规则数组,需要确定数组大小,但是会出现定义数组长度太小或太大导致内存浪费或者不够)的属性是Array,所以在实现StudentDao的方法时,就会有不同的具体的实现方法。

Q5.什么是面向接口编程?面向接口编程的好处是什么?结合题目3与4中的Test.java的代码讨论分析。不要百度原封不动照搬!

  • 面向接口编程:将代码与接口相联系,但是编写不需要考虑有什么类实现了该接口。只要一旦有类实现该接口,直接用这个接口代码实现就行。这样的好处是提高了程序的灵活性,降低类与类之间的耦合性,通过用接口实现了多态。
  • 在题目3,Comparable可以对本身支持排序的类进行排序,当你需要对某个类进行整体排序就可以直接实现Comparable,而当你想对类进行某一种(或多种)规则排序就可以实现Comparator接口。在题目4中,只需要注意是用什么数据结构来存放数组,Array还是Arraylist,它们都实现了StudenDao接口,只需对接口方法进行重写即可,这样就可以做到扩展了程序的灵活性,通过重写接口方法,实现多态。

Q6.结对编程:面向对象设计(大作业2-非常重要)
 内容:使用Java代码完成上周做的面向对象设计大作业,需要有初步界面。实现的功能尽量简单,少而精,只包含必要的功能,不要追求高大全。
 写出:类图(尽量精简,不用太多子类,两个即可)、系统常用功能描述、关键代码与界面
 形式: 两人依托码云合作完成。请在这里贴出你们的学号、姓名与任务分工。
 注意: 再过几次课要讲Java图形界面编程,到时候要将该系统升级为图形界面。系统的业务逻辑部分应该变化不大,变化大的是输入与输出部分。所以编码的时候,输入   (Scanner)与输出(System.out)的代码,请不要将其与某个业务处理函数绑死。
 选做加分: 给出两人在码云上同一项目的提交记录截图,额外加分。注:两个人在码云上新建一个项目。
 参考资料:结对编程参考资料 可以使用Processon画图

  • 6.1
学生A 项目地址
http://www.cnblogs.com/xygeqian/p/6610434.html https://git.oschina.net/xygeqian/java201521123013/tree/master
  • 6.2常用功能描述框图
      

  • 6.3关键代码

public class Clothes extends Goods {
	private String color;
	private String size;
	public Clothes(String name,double price,int num,String color, String size) {
		super(name,price,num);
		this.color = color;
		this.size = size;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	public String getSize() {
		return size;
	}
	public void setSize(String size) {
		this.size = size;
	}
	@Override
	public String toString() {
		return "衣服:"+super.getName()+",价格:"+super.getPrice()+",颜色:"+color+",尺寸"+size+",数量:"+super.getNum();
	}
	
}

public abstract class Goods {
	private String name;
	private double price;
	private int num;
	
	public Goods(String name, double price, int num) {
		super();
		this.name = name;
		this.price = price;
		this.num = num;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

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

	@Override
	public String toString() {
		return "Goods [name=" + name + ", price=" + price + ", num=" + num + "]";
	}
}
  • 6.4运行界面
      

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

3.1本周Commit历史截图

  

3.2 实验总结

  1. 在5-1中,因为是在姓名相同的情况下对年龄进行排序,所以只需要用Comparable接口,当if(this.name.compareTo(o.name)!=0){return this.name.compareTo(o.name);else {return Integer.toString(this.age).compareTo(Integer.toString(o.age));}
  2. 在5-2中,因为需要对姓名和年龄分别进行排序,所以用到两个比较器NameComparator和AgeComparator。写法跟5-1一样,可以通过匿名内部类或者lambda表达式的方式写。两题的注意当compare值大于0返回1,当小于0返回-1。
  3. 4-1对题目理解不是很清楚,运行不出来结果。

posted @ 2017-03-25 20:53  _Another  阅读(215)  评论(0编辑  收藏  举报