1. 本周学习总结
2. 书面作业
1.代码阅读:Child压缩包内源代码
1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误。并分析输出结果。
1.2 另外一个包中的OutOfParentPackage.java,能否编译通过?提示什么错误?分析原因。
1.3 回答:如果为了访问到protected修饰的属性或方法应该怎么办?
答:(1)Child.java文件不能编译通过,System.out.println(i)会出错,因为父类Parent的i是被private定义,即i只能被父类自身访问;所以应该把private改为protected。
输出结果为
c.getParenti();输出父类Parent的i,虽然这边没有使用super,但是子类Child没有重新定义i,所以输出的还是父类的i=1;c.getParentj();输出父类的j,父类的j,父类的i和父类的i。子类没有重新定义j和i,这边加不加super结果都是一样的。Other.showParentj(p);输出父类的j和父类的i,因为是static修饰的,所以直接用类名调用。
(2)提示错误**The type Parent is not visible**,需要将parent文件中的protected int j=2 protected int geti()改为public int j=2; public int geti()才能通过编译。
(3)同一个包内访问到protected修饰的属性或方法要使用super(),不同包则要把访问权限定义为public。
2.abstract进阶:阅读GuessGame抽象类的设计与使用源代码
2.1 Guess改造前代码很简单,而改造后的代码使用了抽象类、抽象方法看起来很复杂,那这样的改造到底有什么好处呢?
2.2 如果想将该游戏改造成图形界面,应该进行一些什么操作?
2.3 结合该例子,你觉得什么时候应该使用abstract?
2.4 重要:在这个例子中,变化的是什么,不变的是什么?尝试结合abstract、继承等概念进行说明。
//改造前的
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();//这边使用了抽象类GuessGame
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();
}
答:(1)改造前,未使用抽象类,只能控制台输出;改造后,使用抽象类,可以在控制台,也可以使用对话框图形界面等输入。
(2)利用Javax Swing,系统能够根据用户的输入给出用户的猜测结果。
(3)抽象类定义:包含抽象方法的类,抽象类必须在类前用abstract关键字修饰。抽象方法是一种特殊的方法:它只有声明,而没有具体的实现,抽象方法必须用abstract关键字进行修饰。所以当项目有大体的框架,没有具体的方法,就要使用abstract,然后在子类中具体实现方法。
(4)这个例子中,输入和输出是变化的,但是对生成随机数,比较输入数和生成数的方法是不变的。父类GuessGame使用abstract,声明了数字处理方法,而子类继承并覆盖父类的方法。
3.Comparable与Comparator
3.1 描述Comparable接口的用途。为什么某个类实现了Comparable接口就可以直接使用Arrays.sort对其进行排序?
3.2 有了Comparable接口为什么还需要Comparator接口呢?
3.3 可选:使用匿名内部类、Lambda表达式实现PTA编程5-2。
答:(1)Comparable接口强行对实现它的每个类的对象进行整体排序。此排序被称为该类的自然排序,类的compareTo方法被称为它的自然比较方法 。实现此接口的对象列表(和数组)可以通过 Collections.sort (和 Arrays.sort )进行自动排序。
(2)
底下的是我从百度搜索得到的结果
①、Comparator位于包java.util下,而Comparable位于包java.lang下。
②、Comparable接口将比较代码嵌入需要进行比较的类的自身代码中,而 Comparator接口在一个独立的类中实现比较。
③、如果前期类的设计没有考虑到类的Compare问题而没有实现Comparabl e接口,后期可以通过Comparator接口来实现比较算法进行排序,并且为 了使用不同的排序标准做准备,比如:升序、降序。
④、Comparable接口强制进行自然排序,而Comparator接口不强制进行自 然排序,可以指定排序顺序。
4.面向接口案例分析
阅读Case-StudentDao.zip案例
4.1 画出类关系图,描述每个类与接口的作用。
4.2 StudenDaoListImpl与StudentDaoArrayImpl有何区别?
答:(1)
-
Studen类:用来创建对象.
-
StudentDao接口:抽象类,声明
public Student readStudent
,public boolean writeStudent
和public void diplayAllStudent
三个抽象方法. -
StudentDaoArrayImpl类:
public StudentDaoArrayImpl(int size)
创建一个长度为size的数组;public Student readStudent
输入一个名字,若students数组中有学生的name与输入的名字相等,则返回该学生,否则返回null;public boolean writeStudent
输入一个学生,若数组中某个元素为空,则把此学生加入students数组,并返回true,否则返回false;public void diplayAllStudent
输出全部的学生. -
StudenDaoListImpl类:创建一个以Student对象的ArrayList,并命名List;
public Student readStudent
输入一个名字,若List中有学生的name与输入的名字相等,则返回该学生,否则返回null;public boolean writeStudent
输入一个学生,加入List,并返回true;public void diplayAllStudent
输出List的全部学生.
(2)StudenDaoListImpl是以固定数组来存储学生,数量有限制。
StudentDaoArrayImp是以可变数组来存储学生,数量不限。
5.什么是面向接口编程?面向接口编程的好处是什么?
答:面向接口编程:面向接口编程就是将方法的声明与实现分开,创建接口时只需声明方法而不具体定义该方法的实现,具体的实现过程放在某个类中,类要实现接口。
面向接口编程的好处:在修改某个模块时,不必引起其他模块的大改动。
题目四中Test.java文件,定义一个StudentDao接口,对学生信息进行写入,读取,显示等操作,只需在接口声明抽象方法,不需定义方法的实现(如StudentDao接口下的三个抽象方法),具体的实现过程放在某个类中。例如StudentDaoArrayImpl类是将学生信息存入数组中,但是一开始就让我们定下数组长度,若长度不足则要重新定义数组长度重新输入数据,因而有局限性。此时我们并不需要修改StudentDaoArrayImpl类中的代码,只需要重新写一个StudenDaoListImpl类,在main调用StudentDao接口的抽象方法,就不用改动现有代码。
3. 码云上代码提交记录及PTA实验总结
3.2.实验总结
第一题的compareTo方法的具体实现:在比较名字时我本来是写了多个if(>0,<0,==0),每个if返回一个值x(=-1,=1,=0),这样比较麻烦。后来修改为x=this.name.compareTo(o.name);这样直接返回x的值,减少代码量。