1. 本周学习总结
1.1 尝试使用思维导图总结有关继承的知识点。
1.2 使用常规方法总结其他上课内容。
(1)文档注释(类注释、方法注释、属性注释、通用注释、)(2)多态性、instanceof运算符(判断引用的对象实例的实际类型)(3)强制转换(基本类型和引用类型都可以使用强制转换,父类在强制转换成子类之前,最好用instanceof进行判断)(4)抽象方法必须被重写,抽象方法只能有声明,不能有实现。(5)控制可见性的访问修饰符:private(在本类中可见)、public(对所有类可见)、protected(对同包和所有子类可见)、默认(对本包可见,不推荐)(6)Object类(所有类的父类):toString方法(输出对象所属的类名和散列码)、equals方法(判断两个对象是否有相同的引用)、hashCode方法
2. 书面作业
Q1.注释的应用 使用类的注释与方法的注释为前面编写的类与方法进行注释,并在Eclipse中查看。(截图)
Q2. 面向对象设计(大作业1,非常重要) 2.1 将在网上商城购物或者在班级博客进行学习这一过程,描述成一个故事。(不得少于50字,参考QQ群中PPT的范例) 2.2 通过这个故事我们能发现谁在用这个系统,系统中包含的类及其属性方法,类与类之间的关系。尝试找到这些类与属性,并使用思维导图描述类、属性、方法及类与类之间的关系。 2.3 尝试使用Java代码实现故事中描述的这一过程(不必很完善),将来要在这个基础上逐渐完善、扩展成一个完整的面向对象的系统。(可选:加分) 参考资料: UML类图 面向对象案例-借款者姓名地址.zip 2.1答:周一中午,我在食堂排队的时候接到我妈打来的电话,她让我在网上给我爸买个手机。我在纠结该买哪个牌子的手机,舍友们说华为这个牌子不错,而且挺适合男生用。于是,吃完饭回到宿舍,我就打开电脑,输入京东官网地址,登入自己的账号,在搜索栏输入华为手机,选择屏幕尺寸为5.1-5.5英寸,运行内存为3GB,机身内存为16GB,然后出现满足这些条件的华为手机,我开始查看它的评价及售后保障并对其进行筛选,比较喜欢的就将它添加到购物车,最后在购物车中选择最满意的一款,然后点击结算,填好收货地址及联系电话,然后完成支付。
2.2
2.3
商品类class Goods {private double price;private int nums;private String type;public Goods(double price, int nums, String type) { super(); this.price = price; this.nums = nums; this.type = type;}public double getPrice() { return price;}public int getNums() { return nums;}public String getType() { return type;}@Overridepublic String toString() { return "Goods [price=" + price + ", nums=" + nums + ", type=" + type + "]";}public void search(){...}
华为手机类
class HW_Phone extends Goods{ private double ScreenSize; private String RAM; private String ROM; private String capacity; public HW_Phone(double price, int nums, String type, double screenSize, String rAM, String rOM, String capacity) { super(price, nums, type); ScreenSize = screenSize; RAM = rAM; ROM = rOM; this.capacity = capacity; } public double getScreenSize() { return ScreenSize; } public String getRAM() { return RAM; } public String getROM() { return ROM; } public void setROM(String rOM) { ROM = rOM; } public String getCapacity() { return capacity; } @Override public String toString() { return "HW_Phone "+super.toString()+"[ScreenSize=" + ScreenSize + ", RAM=" + RAM + ", ROM=" + ROM + ", capacity=" + capacity + "]"; } }
购物车类
class ShoppingCar{ private Goods goods; private Users user; @Override public String toString() { return "ShoppingCar [goods=" + goods + ", user=" + user + "]"; } public void add(){ ... } public void delete(){ ... } public double sum(){ ... } public void find_similar(){ ... } }
用户类
class Users{private String pname;private String adress;private String tel;public Users(String pname, String adress, String tel) { super(); this.pname = pname; this.adress = adress; this.tel = tel;}@Overridepublic String toString() { return "Users [pname=" + pname + ", adress=" + adress + ", tel=" + tel + "]";}
Q3.ManagerTest.zip代码分析 分析ManagerTest.zip中的代码,回答几个问题: 3.1 在本例中哪里体现了使用继承实现代码复用?回答时要具体到哪个方法、哪个属性。 3.2 Employee类及其子类Manager都有getSalary方法,那怎么区分这两个方法呢? 3.3 文件第26行e.getSalary(),到底是调用Manager类的getSalary方法还是Employee类的getSalary方法。 3.4 Manager类的构造函数使用super调用父类的构造函数实现了代码复用,你觉得这样的有什么好处?为什么不把父类构造函数中的相关代码复制粘贴到Manager的构造函数中,这样看起来不是更直观吗?
3.1答:子类Manager的getSalary方法中复用了父类Employee类的getSalary方法,子类Manager的构造方法中复用了父类Employee类的构造方法。属性name,salary,hireDay也实现了代码复用。
3.2
答:JVM会根据调用该方法的实际对象类型来判断调用哪个方法,即若实际对象类型为Manager,则调用Manager类的getSalary方法,若实际对象类型为Employee,则调用Employee类的getSalary方法。
3.3
答:当e=staff[0]时,调用了Manager类的getSalary方法,当e=staff[1]或e=staff[2]时,调用了Employee类的getSalary方法。
3.4
答:好处:大大提高了软件开发的效率,提高了程序的可维护性。把父类构造函数中的相关代码复制粘贴到Manager的构造函数中,如果对父类构造函数中的相关代码进行了修改,那么同时也要对Manager的构造函数进行修改,而当Manager类的构造函数使用super调用父类的构造函数实现了代码复用时,只需对父类进行修改即可。
Q4.Object类 4.1 编写一个Fruit类及属性String name,如没有extends自任何类。使用System.out.println(new Fruit());是调用Fruit的什么方法呢?该方法的代码是从哪来的?尝试分析这些代码实现了什么功能? 4.2 如果为Fruit类添加了toString()方法,那么使用System.out.println(new Fruit());调用了新增的toString方法。那么其父类中的toString方法的代码就没有了吗?如果同时想要复用其父类的toString方法,要怎么操作?(使用代码演示) 4.3 Fruit类还继承了Object类的eqauls方法。尝试分析其功能?自己编写一个equals方法覆盖父类的相应方法,功能为当两个Fruit对象name相同时(忽略大小写),那么返回true。(使用代码证明你自己覆盖的eqauls方法是正确的) 4.4 在4.3的基础上使用ArrayList<Fruit> fruitList
存储多个fruit
,要求如果fruitList
中已有的fruit
就不再添加,没有的就添加进去。请编写相关测试代码。并分析ArrayList
的contatins
方法是如何实现其功能的?
答:使用System.out.println(new Fruit());是调用Fruit的toString()方法,Fruit类继承Object类,Object类中有toString方法,Fruit类对Object类的toString方法实现了复用。这些代码返回一个字符串(字符串内容:Class对象所代表的具体对象的名称与该对象哈希码值的16进制形式)。
4.2
答:父类中的toString方法的代码仍然有。4.3
答:功能:判断当前对象与传入对象是否有相同的引用,如果有返回true,否则返回false.
代码:
class Fruit{ private String name; public Fruit(String name) { super(); this.name = name; } @Override public boolean equals(Object obj) { // TODO Auto-generated method stub Fruit other=(Fruit) obj; if((name.compareToIgnoreCase(other.name))==0){ return true; } return false; } @Override public String toString() { return super.toString()+" Fruit [name=" + name + "]"; } }public class Main { public static void main(String[] args) { // TODO Auto-generated method stub Fruit f1=new Fruit("apple"); Fruit f2=new Fruit("Apple"); System.out.println(f1.equals(f2)); }}
4.4
import java.util.ArrayList;import java.util.Scanner;class Fruit{ private String name; public Fruit(String name) { super(); this.name = name; } @Override public boolean equals(Object obj) { // TODO Auto-generated method stub Fruit other=(Fruit) obj; if((name.compareToIgnoreCase(other.name))==0){ return true; } return false; } @Override public String toString() { return "Fruit [name=" + name + "]"; } }public class Main { public static void main(String[] args) { // TODO Auto-generated method stub ArrayListfruitList=new ArrayList<>(); Scanner in=new Scanner(System.in); int n=in.nextInt(); for (int i = 0; i < n; i++) { String str=in.next(); Fruit f=new Fruit(str); if(i==0){ fruitList.add(f); } else{ if(!fruitList.contains(f)){ fruitList.add(f); } } } System.out.println(fruitList); }}
答:通过遍历elementData数组来判断对象是否在fruitList中,若存在,返回对象在数组中的元素下标,若不存在则返回-1。ArrayList中的contains方法可以通过indexOf(Object)方法的返回值来判断对象是否被包含在fruitList中,若返回值大于等于0,则返回true,否则返回false。
代码阅读:EqualsTest.java(equals与hashCode) 5.1 读懂main函数,将自己推测的出代码运行结果与真正运行结果进行比较。尝试分析原因 5.2 为Employee类的equals函数的每一行加中文注释。 5.3 为Manager类的equals函数的每一行加中文注释。并回答,编写子类的equals函数需要注意什么? 5.4 对Employee的hashCode源代码,加中文注释。并结合数据结构中的知识,你觉得每个类中都有的hashCode方法有什么用? 5.5 查看Manager的hashCode源代码。并回答,编写子类的hashCode方法需要注意什么?
5.1 结果:分析:注意"=="比较的是引用值,调用equals()方法时,JVM会根据实际对象类型来选择调用哪个方法,只需对方法中的条件进行判断。注意不要漏看"boss.setBonus(5000);"这一句,否则在判断"System.out.println("carl.equals(boss): " + carl.equals(boss));"时就会判断错。
5.2
5.3答:编写子类的equals函数注意可以复用父类的equals函数。
5.4
public int hashCode() { int h = hash;//将hash的值赋给h if (h == 0 && value.length > 0) {//如果h的值为0并且value数组的长度不为0 char val[] = value;//将value数组赋给val数组 for (int i = 0; i < value.length; i++) {//i从0变化到value.length-1时满足循环条件 h = 31 * h + val[i];//h与val[i]一一映射 } hash = h;//将h的值赋给hash } return h;//返回h的值 }
答:返回该对象的哈希码值。每创建一个对象,根据该对象的哈希码值,可将其插入到Hash表中,若不同对象的哈希码值相同,也就是在key位置发生了冲突,那么就在key位置新建一个链表,将相同哈希码的不同对象插入链表。比较两个对象时,首先比较的是它们的哈希码值,若哈希码值不同,则肯定不equal。
Q6.代码阅读:PersonTest.java(abstract、多态) 6.1 画出类的继承关系 6.2 读懂main函数,将自己推测的出代码运行结果与真正运行结果进行比较。尝试分析原因 6.3 子类中里面使用了super构造函数,作用是什么?如果将子类中的super构造函数去掉,行不行? 6.4 PersonTest.java中的代码哪里体现了多态?你觉得多态有什么好处?多态和继承有什么关系吗? 参考文件:PersonTest.java
6.16.2
运行结果: 分析:按年龄从小到大对数组peoples进行排序,并根据调用toString()方法的实际对象类型来选择调用哪个方法。例如:peoples[3]实际是Manager类,则调用Manager类的toString()方法,而Manager的toString()方法中又使用了super.toString(),即调用了Employee类的toString()方法,依此类推,Employee类的toString()方法调用了Person类的toString()方法,将Manager的toString()方法输出即可。6.3
答:调用父类的构造函数,对子类中与父类相同的属性进行初始化。不能将子类中的super构造函数去掉。
6.4
多态体现:多态的好处:可以增强程序的可扩展性及可维护性,使代码更加简洁。多态和继承的关系:继承是多态的前提。
3. PTA实验总结及码云上代码提交记录
3.1本周Commit历史截图
3.2 实验总结
实验碰到的问题、思考、收获与解决方案
实验碰到的问题:(1)输出persons2数组(ArrayList容器)中的每个元素,使用for(int i=0;i