201521123006 《Java程序设计》第5周学习总结
1. 本周学习总结
1.1 尝试使用思维导图总结有关多态与接口的知识点。
1.2 可选:使用常规方法总结其他上课内容。
- 接口与抽象类拥有相同之处:(1)都代表系统的抽象层。
(2)都不能被实例化(不能new)
(3)都能包含抽象方法。这些抽象方法只用于描述,但不必提供具体的实现。 - 接口与抽象类的不同之处: (1)在抽象类中可为部分方法提供默认的实现,从而避免在子类中重复实现,提高代码的可重用性。而接口则不能。
(2)在某个类中可以实现多个接口,但只能继承一个类。 - Java中常用的接口:(1)ActionListener() //监听接口
(2)Comparable //比较接口
(3)Serializable //序列化接口
(4)Runnable //多线程接口
2. 书面作业
**1. 代码阅读: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 Test01 extends Parent{
public static void main(String[] args){
Parent p = new Parent();
Test01 c = new Test01();
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());
}
}
(1)不能编译通过。
(2)System.out.println(i);
这句会出错。
(3)这句会出错的原因在于父类中的i为private修饰,父类中的i对于子类来说是不可见的。
(4)所以改正错误可以将private 改为 protected。
(5)运行输出结果:
1
2
2
1
1
2
1
首先,第一个“1”,则是c.getParenti();
输出父类的i,而在父类初始化时i=1。
其次,之后的“2,2,1,1”,则是c.getParentj();
输出父类的j,父类的j,父类的i,父类的i,而父类的j在初始化时j=2,而且子类中未重新定义i和j,所以i,j都是父类的。
最后,最后的“2,1”,则是Other.showParentj(p);
输出父类的j和父类的i。
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();
}
}
(1)不能编译通过。
(2)提示的错误:The type keke.Parent is not visible
(3)因为OutOfParentPackage.java在com.Parent包之外,所以访问不到。
(4)根据提示把Parent改为public修饰的之后,发现依然错误。然后再根据提示将Parent中的j和geti()从protected修饰改为public修饰的。改造后的Parent类为:
此时,程序编译成功了,运行结果为:
1.3 回答:如果为了访问到protected修饰的属性或方法应该怎么办?
因为protected修饰的属性和方法是可以在本包和子类访问,所以一种方法是只要有继承关系,子类就可以用super去访问父类中定义的protected修饰的方法或属性,这是我们就可以不用管子类和父类是不是在同一个包中;而另一种方法则是使需要访问protected修饰的属性或方法的类,他们在同一个包就行。
**2. abstract进阶:阅读GuessGame抽象类的设计与使用源代码 **
**2.1 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");
}
}
改造后:
//Guess.java
package cc.openhome;
public class Guess {
public static void main(String[] args) {
GuessGame game = new ConsoleGame();//抽象类
game.go();
}
}
//classGuess.java
package cc.openhome;
public abstract classGuess {
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();
}
好处(PS:由文件名可以知道):
- 改造前,未使用抽象类,只能控制台输出
- 改造后,使用抽象类,可以在控制台,也可以使用对话框图形界面等输入
**2.2 如果想将该游戏改造成图形界面,应该进行一些什么操作? **
在改造后的基础上重新再设计一个关于图形界面的类,并且这个类需要继承ConsoleGame()即需要继承我们原来写的抽象类,并且要使得我们的输入输出在图形界面中的话,则需要我们在图形界面中重新定义输入输出语句, 覆盖父类中的语句。
**2.3 结合该例子,你觉得什么时候应该使用abstract? **
- 使用abstract修饰的类,是抽象类
- 比如有些东西在许多类中有用得到,但是又不能够作为一种工具进行使用或者出现,这是就可以考虑使用抽象类,然后再需要用到的类中进行继承,有需要统一改动的地方只需要更改抽象类就行了,不需要将每个类都逐一更改,并且需要增添其他功能时,也只需设计好类后继承抽象类就行。
就像本题中,我们没有后决定好使用哪种环境平台,界面显示时,就要使用抽象类,抽象类可以让这个游戏能够方便地根据需要进行改变或者增添功能。
**2.4 重要:在这个例子中,变化的是什么,不变的是什么?尝试结合abstract、继承等概念进行说明。 **
- 变化的是:使用的环境,例如:在改造前只能使用控制台输出,但是在改造后,使用了抽象类,就可以在控制台,也可以使用对话框图形界面等不同的环境输入输出。
- 不变的是:抽象类。我们决定使用哪种环境平台,都不会改变抽象类,抽象类本身就包含着多种的输入输出方式。我们只需根据所需的功能进行设计类,之后只需要使我们设计的类继承抽象类就行了,如果有需要实现具体细节或者具体的输入输出等功能时,只需在子类中重写语句进行。
**3. Comparable与Comparator **
**3.1 描述Comparable接口的用途。为什么某个类实现了Comparable接口就可以直接使用Arrays.sort对其进行排序? **
(1)Comparable接口一般用于需要排序的对象不是简单的数字型,这时就可以使用Comparable接口就行简单排序,或者自定义排序。
(2)因为查看sort的原型,我们不难发现sort为:
这说明此时需要排序的集合已经实现了Comparable接口,而Comparable接口只有一个 compareTo 方法,并且只要重写compareTo这个方法就可实现自动排序,这样就不用自己写一个排序的方法,更加方便。
**3.2 有了Comparable接口为什么还需要Comparator接口呢? **
因为Comparable接口是定义在类内部,是强行对是实现它的每个类的对象进行整体排序,且只有一种排序方式,而Comparator接口则是定义在类的外部,比较是在一个独立的类中实现,对于Comparator接口来说,它的比较是能够为进行不同的排序做准备,比如:升序、降序。所以Comparator接口可以算是对于Comparable接口的一种完善或者是功能的补充,可以实现多种排序。
**4. 面向接口案例分析 **
**阅读Case-StudentDao.zip案例 **
**4.1 画出类关系图,描述每个类与接口的作用。 **
- Student类:属性只有String name。方法为:getName(),setName(),toString(),Student的构造函数。是StudenDaoListImpl和StudentDaoArrayImpl的父类。
- StudentDao接口:提供三个抽象方法,writeStudent(),readStudent(),diplayAllStudent()。
- StudentDaoArrayImpl类:使用数组来存放学生信息。具体实现接口的三个抽象方法,读取学生信息,输入学生信息,遍历学生信息输出。以及自己的构造函数。
- StudenDaoListImpl类:使用列表来存放学生信息。与StudentDaoArrayImpl类同样是具体实现接口的三个抽象方法。
**4.2 StudenDaoListImpl与StudentDaoArrayImpl有何区别? **
主要区别就是:StudenDaoListImpl使用的是列表来存放学生信息,从而使得部分方法的使用有别与StudentDaoArrayImpl的方法使用。而StudentDaoArrayImpl使用的是数组来存放学生信息,读取和写入学生信息都是使用数组的方法。
**5. 什么是面向接口编程?面向接口编程的好处是什么? **
**结合题目3与4中的Test.java的代码讨论分析。不要百度原封不动照搬! **
- 面向接口编程就是相当于我们把需要的方法提取出来,作为接口。方法具体实现通过该接口的实现类来完成。而我们针对需求,编写的实现类,编写的具体方法,就可以认为是面对接口编程。在题目3中便有使用 Comparable与Comparator接口,对其 CompareTo方法与Compare方法进行覆盖,从而可以直接使用Array中的sort()方法。而在题目4中使用了StudentDao接口,在接口中编写了所需要的三个抽象类方法,而后在StudentDaoArrayImpl类和StudenDaoListImpl类编写,具体实现这三种抽象方法。
- 面向接口编程的好处:从题目3和题目4中,我们可以明显感觉到面对接口编程,当需求有变化时,只需根据新的需求来编写新的类就行,不需要对现有的代码进行修改,减少了对于系统的影响,减少了我们的工作量,也避免了出现不必要的错误,增加了程序的灵活性,方便我们在原有的代码上进行修改功能,进行扩展。
**6. 结对编程:面向对象设计(大作业2-非常重要) **
内容:使用Java代码完成上周做的面向对象设计大作业,需要有初步界面。实现的功能尽量简单,少而精,只包含必要的功能,不要追求高大全。
**写出:类图(尽量精简,不用太多子类,两个即可)、系统常用功能描述、关键代码与界面 **
**形式: 两人依托码云合作完成。请在这里贴出你们的学号、姓名与任务分工。 **
注意: 再过几次课要讲Java图形界面编程,到时候要将该系统升级为图形界面。系统的业务逻辑部分应该变化不大,变化大的是输入与输出部分。所以编码的时候,输入(Scanner) 与输出(System.out)的代码,请不要将其与某个业务处理函数绑死。
选做加分: 给出两人在码云上同一项目的提交记录截图,额外加分。注:两个人在码云上新建一个项目。
第6题提交作业的结构:
6.1
(PS:本来是两个人一起写的,但是后面合不起来,就各写各的了)
徐婉萍 | 项目地址 |
---|---|
http://www.cnblogs.com/KimHeechul/p/6614099.html | https://git.oschina.net/KimHeechul/Java201521123006/commit/d7ceaa5eb223a233c8ac1d2bec108099913a18ca |
**6.2 常用功能描述框架图 **
**6.3 关键代码 **
class product{
public String name;
public double price;
public product(String name, double price) {
this.name=name;
this.price=price;
}
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;
}
@Override
public String toString() {
return "product [name=" + name + ", price=" + price + "]";
}
}
class ShoppingCart extends product{
public int num;
public double sum;
public ShoppingCart(String name,double price,int num) {
super(name,price);
this.num = num;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public double getSum() {
return sum;
}
public void setSum(double sum) {
this.sum = sum;
}
@Override
public String toString() {
return "ShoppingCart [name=" + name + ", price=" + price + ", num=" + num+"]";
}
ArrayList <product> Goods = new ArrayList<product>();
public void add(product goods){
this.Goods.add(goods);
}
public double sumShoppingCart(){
double sum = 0;
for(product goods:Goods){
sum+=goods.getPrice()*((ShoppingCart) goods).getNum();
}
return sum;
}
public boolean deleteShoppingCart(int index){
if(index>=0&&index<Goods.size()){
product goods;
goods=Goods.get(index);
sum-=goods.getPrice()*((ShoppingCart) goods).getNum();
Goods.remove(index);
return true;
}
else
return false;
}
}
class Login {
private String name="xwp";
private String secret="123456";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSecret() {
return secret;
}
public void setSecret(String secret) {
this.secret = secret;
}
public Login(String name, String secret) {
super();
this.name = name;
this.secret = secret;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Login other = (Login) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (secret == null) {
if (other.secret != null)
return false;
} else if (!secret.equals(other.secret))
return false;
return true;
}
}
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
ArrayList<ShoppingCart> shoppingcarts = new ArrayList<ShoppingCart>();
product[] goods = new product[5];
goods[0] = new product("Java", 65.3);
goods[1] = new product("Math", 37.2);
goods[2] = new product("skirt", 80.0);
goods[3] = new product("jacket", 46.8);
goods[4] = new product("Ajax", 65.3);
System.out.println("请输入帐号和密码:");
Login account = new Login(in.next(), in.next());
Login obj = new Login("xwp", "123456");
if (!account.equals(obj)) {
System.out.println("帐号或密码错误!");
return;
}
System.out.println("登入成功!");
while (true) {
System.out.println("请输入要搜索的商品名:");
String name = in.next();
int i;
for (i = 0; i < goods.length; i++) {
if (name.equals(goods[i].getName())){
System.out.println(goods[i]);
break;
}
}
if (i == goods.length){
System.out.println("找不到该商品!");
return;
}
else {
System.out.println("1.添加至购物车并查看 2.结算此商品 3.结算购物车及此商品");
int choice=in.nextInt();
if ( choice== 1)
{
System.out.println("输入需要的数量");
ShoppingCart shoppingcart = new ShoppingCart(goods[i].getName(), goods[i].getPrice(),in.nextInt());
shoppingcarts.add(shoppingcart);
System.out.print("显示购物车");
System.out.println(shoppingcarts);
}
else if (choice == 2){
System.out.println("输入此商品需要的数量");
double sum = 0.0;
ShoppingCart shoppingcart = new ShoppingCart(goods[i].getName(), goods[i].getPrice(),in.nextInt());
sum += shoppingcart.getPrice()*shoppingcart.getNum();
System.out.println("总价:");
System.out.println(sum);
}
else if(choice == 3){
System.out.println("输入此商品需要的数量");
double sum = 0.0;
for (ShoppingCart shoppingcart : shoppingcarts) {
sum += shoppingcart.getPrice()*shoppingcart.getNum();
}
sum+=goods[i].getPrice()*in.nextInt();
System.out.println("总价:");
System.out.println(sum);
}
}
}
}
}
**6.4 运行界面 **
3. 码云上代码提交记录及PTA实验总结
**题目集:jmu-Java-04-面向对象2-进阶-多态接口内部类 **
**3.1. 码云代码提交记录 **
**在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图 **
**3.2. PTA实验 **
继续完成前面未完成的实验面向对象1-基础-封装继承
函数(选做:4-1)、编程(5-1, 5-2)
一定要有实验总结
- 5-1:主要是使用Comparable接口,利用compareTo方法进行比较,排序。
- 5-2:主要是使用Comparator接口,利用compare方法针对姓名和年龄分别进行比较,排序。