20162330 第三周 蓝墨云班课 泛型类-Bag 练习
- 题目及要求
- 思路分析
- 遇到的问题和解决过程
- 代码实现及托管链接
- 感想
- 参考资料
题目及要求
- 代码运行在命令行中,路径要体现学号信息,IDEA中,伪代码要体现个人学号信息;
- 参见Bag的UML图,用Java继承BagInterface实现泛型类Bag,并对方法进行单元测试(JUnit),测试要涵盖正常、异常情况、边界情况;
- 课上提交测试代码和测试运行的结果截图,截图要求全屏截图,包含自己的学号信息,否则无效;测试Bag类的代码中至少包含一个自定义类如Student;
- 课下完成码云上代码的上传。
- 【附】Bag的UML图:
【返回目录】
思路分析
- 首先自定义一个Bag类,使用
public class Bag<T> implements BagInterface<T>
实现给出接口的所有方法框架,之后在里面通过泛型类型 T 自定义一个数组,通过填充方法来完善Bag类。考虑到给出的接口含有add
、remove
、isEmpty
等方法,如果使用 List 创建对象实现有些简单,所以我选择了使用 Object 类定义数组实现这些方法。
在 Bag 类的 UML类图 中,我们可以清楚地知道每个方法的返回类型、参数及需要实现的功能,大部分功能的实现比较框架化,比如:getCurrentSize()
、isEmpty
、add(T newEntry)
、remove()
等,其方法填充内容基本符合以下框架:
public <返回类型> <函数名>(<参数>){//初始化返回值参数对象//循环(遍历、修改元素)//条件(何时修改、赋值)//返回值(参数)
}
之所以能用 循环 + 条件 的框架是因为这些方法基本都涉及遍历环节,我也使用了几种不同的遍历方式。
需要注意的是最后一个方法 toArray()
,这个方法相对陌生,我查找了API,关键句如下:
按 适当顺序 返回包含此列表中所有元素的数组;
如果指定的数组能容纳队列,并有剩余的空间,那么会将数组中紧接 collection 尾部的元素设置为 null。
所谓的“适当顺序”,可以理解为不同与原来数组排列元素的顺序,我又继续看了UML类图中的这一方法的注释:
A new array of entries currently in the bag.
- 我的思路是将原来数组中的空值元素都填补为同一类型的相同的值,然后再重新返回这个数组,这样就可以通过一个含空值的数组调用此方法之后的元素容量进行单元测试。实现代码如下:
/*Shows all objects in a new array of food bag entries.*/public T[] toArray() {int j = food.length - 1;for (int i = 0;i<food.length;i++) {food[j] = "apple";if (food[i] == null) { //将空值全部填补food[i] = food[j];j--;}}return (T[]) food;}
【返回目录】
遇到的问题和解决过程
【问题】在使用Junit测试
add(T newEntry)
方法时,Junit测试异常:
- 【解决方法】我仔细看了一下自己写的 add 方法:
public boolean add(T newEntry) {boolean boo = false;for (Object i : food) {if (i == null) {i = newEntry; //添加到第一个空值位置boo = true;break;}}return boo;}
由于使用foreach遍历比较简单,我就没有考虑其他问题。IDEA的提示,给 i 重新赋值的那条语句中的 i 是多余的:
![](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007184208240-2031952014.png)我就想不通为什么是多余的,于是又开始检查 foreach 的结构框架:
for(<元素类型> <元素变量> : <遍历对象>){引用元素变量的相关语句;
}
修改了几次数组类型之后还是不对,于是我认为是foreach方法出现问题,就做了一个foreach的测试类,发现果然是foreach方法的问题,同样的修改赋值语句,使用for循环遍历就正常,使用foreach就不能进行相应赋值:
![](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007185209661-1263550744.png)接着,我开始使用debug单步调试:(单击图片可放大)[![](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007185542708-250193647.png)](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007185542708-250193647.png)刚开始设断点,我并没有注意观察细节,只是跟着步骤走了一遍,又跟踪了一遍才发现给 i 赋值的语句好像并没有效果,这一句出现了问题。我又仔细地跟踪了一遍,发现add元素的地址和原来空值的地址不一样,而最后数组添加的是空值的地址:[![](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007185832974-1747717902.png)](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007185832974-1747717902.png)[![](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007185845349-1292468436.png)](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007185845349-1292468436.png)所以总结起来就是,i 原来对应的地址就不是指向数组元素的,所以只要用其他循环(for循环)替代即可正常修改原数组的元素:![](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007190315911-1971919464.png)如果一定要使用foreach修改数组元素的话,那只能再另外加一层循环:
public boolean add(T newEntry) {boolean boo = false;for (Object i : food) {if (i == null) { //foreach不能修改数组元素for (int j = 0; j < food.length; j++) { //重新使用for循环赋值if (food[j] == i) {food[j] = newEntry; //添加到第一个空值位置break;}}boo = true;break;}}return boo;}
至于我的验证是否正确,我又查找了相关资料,一种说法是:
foreach结构中的元素变量是个基本数据类型,在遍历时不指向数组元素的地址,它只代表数字它自己。
- 还有一个实例可以更好地证明我的验证:
for (Integer temp : list)
{if (temp == 1){temp = temp * 2;}
}
根据oracle的官方文档,正式翻译应该如下:
for (Iterator i = list.iterator(); i.hasNext(); )
{float i0 = (Integer)i.next();if(i0 == 1)i0 = i0*2;
}
所以foreach中的 temp变量只是一个局部变量(i0),而且还是集合中元素的一个副本,并不是元素本身。这样才导致输出“修改过的数组”时,仍然输出原数组。
综上所述,我的验证正确,foreach只适合遍历数组,在实现涉及到修改数组元素的功能时,不宜使用,会造成赋值失败。
【返回目录】
代码实现及托管链接
这里只贴出Bag类代码和运行成功截图,其余代码见相关代码托管链接:
【BagInterface类】
【Bag类】
【BagTest类】- Bag类如下:
/*** A finite number of objects,not necessarily distinct,in no particular order,* and having the same data type(collection).** @author 20162330*/
public class Bag<T> implements BagInterface<T> {private Object food[] = new Object[5];/*Returns the current number of objects in the bag(except null).*/public int getCurrentSize() {int foodSize = 0;for (Object i : food) { //foreach遍历if (i != null)foodSize++;}return foodSize;}/*Demonstrates if the food bag is empty(null).*/public boolean isEmpty() {boolean boo = true; //默认为空for (Object i : food) {if (i != null) {boo = false;break;}}return boo;}/*Adds a given object to the food bag,according to whether the addition succeeds,return true or false.*/public boolean add(T newEntry) {boolean boo = false;for (Object i : food) {if (i == null) { //foreach不能修改数组元素for (int j = 0; j < food.length; j++) { //重新使用for循环赋值if (food[j] == i) {food[j] = newEntry; //添加到第一个空值位置break;}}boo = true;break;}}return boo;}/*Removes an unspecified object from the food bag,if possible.*/public T remove() {Object n = null;for (int i = 0; i < food.length; i++) {if (food[i] != null) {n = food[i];food[i] = null; //移除第一个不为空的元素break;}}return (T) n;}/*Removes an occurrence of a particular object from the food bag,if possible.*/public boolean remove(T anEntry) {boolean boo = false;int i = 0;while (i < food.length) {if (food[i] == anEntry) {food[i] = null;boo = true;break;}i++;}return boo;}/*Removes all objects from the food bag.*/public void clear() {int i = 0;do { //do-while方式遍历food[i] = null;i++;}while (i < food.length);}/*Counts the number of times an object occurs in the food bag.*/public int getFrequencyOf(T anEntry) {int t = 0;for (Object i : food) {if (i == anEntry)t++;}return t;}/*Tests whether the food bag contains a particular object.*/public boolean contains(T anEntry) {boolean boo = false;for (Object i : food) {if (i == anEntry) {boo = true;break;}}return boo;}/*Shows all objects in a new array of food bag entries.*/public T[] toArray() {int j = food.length - 1;for (int i = 0;i<food.length;i++) {food[j] = "apple";if (food[i] == null) { //将空值全部填补food[i] = food[j];j--;}}return (T[]) food;}
}
Junit单元测试截图:(单击图片可放大)
[![](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007193120865-790803238.png)](http://images2017.cnblogs.com/blog/1062725/201710/1062725-20171007193120865-790803238.png)
【返回目录】
感想
- 这次实践中解决问题确实花费了不少时间,不过我一直坚持独立思考,最终顺利解决问题,同时又练习了一下几种不同的循环(遍历)方式,Junit测试与之前相比也更全面了,也算是又体验了一回“做中学”。
参考资料
foreach写失效的问题
蓝墨云班课上的示例BagInterface类
【返回目录】
转载于:https://www.cnblogs.com/super925/p/7635226.html
20162330 第三周 蓝墨云班课 泛型类-Bag 练习相关推荐
- 20162330 第十周 蓝墨云班课 十字链表
作业要求 画出附件中有向图的十字链表:(附件见下图) 示例分析 示例如下: 分析: ① 首先可以标出各个顶点的序号: ② 找到每个顶点对应的入弧和出弧,可以进行标注: ③ 对于每一行的链表,都会有对应 ...
- 20162330 第六周 蓝墨云班课 队列课下作业
作业要求 1 补充课上没有完成的作业 2 参考15.3节,用自己完成的队列(链队,循环数组队列)实现模拟票务柜台排队功能 3 用JDB或IDEA单步跟踪排队情况,画出队列变化图,包含自己的学号信息 4 ...
- 20162330 第六周 蓝墨云班课 队列加分项
作业要求 1 用循环队列实现 2 参考PPT用循环队列打印杨辉三角 3 用JDB或IDEA单步跟踪排队情况,画出队列变化图,包含自己的学号信息 4 把代码推送到代码托管平台 5 把完成过程写一篇博客: ...
- 蓝墨云班课计算机测试题答案,20155317 第一周蓝墨云班课考题
20155317 2016-2017-2 蓝墨云班课考题第2周 上周蓝墨云班课考题 1 ( 单选题 | 1 分) Amdahl定律说明,我们对系统的某个部分做出重大改进,可以显著获得一个系统的加速比. ...
- 20155317 第一周蓝墨云班课考题
20155317 2016-2017-2 蓝墨云班课考题第2周 上周蓝墨云班课考题 1 ( 单选题 | 1 分) Amdahl定律说明,我们对系统的某个部分做出重大改进,可以显著获得一个系统的加速比. ...
- 20155317 2016-2017-2 蓝墨云班课考题第2周
20155317 2016-2017-2 蓝墨云班课考题第2周 三: 1.用gcc -g编译vi输入的代码 2.在main函数中设置一个行断点 3.在main函数增加一个空循环,循环次数为自己学号后4 ...
- 基于蓝墨云平台的计算机教学,基于蓝墨云班课的中职计算机“分层教学”模式探究...
崔月娇 一.教学现状概述 一方面,我校是面向全国招生,部分欠发达地区的学生由于资源配置导致计算机基础相当薄弱,而来自发达地区的学生早早地接触了计算机,部分计算机基础操作已相当熟练,学生的计算机水平参差 ...
- 补交20145226蓝墨云班课 -- 正则表达式作业
蓝墨云班课 -- 正则表达式作业 具体描述: 参考老师在博客园的 Intellj IDEA 简易教程中的单元测试,以TDD的放式学习云班课中"正则表达式简易教程.pdf",在此贴出 ...
- 十字链表画法——蓝墨云班课实践改错
十字链表画法--蓝墨云班课实践改错 课堂题目 分析课堂的错误作业 对十字链表的纵轴理解的不是很清晰,当时画的不完整. 课后的解决 十字链表是为了便于求得图中顶点的度(出度和入度)而提出来的.它是综合邻 ...
- 基于蓝墨云班课的“出门门票”设计与改进
陈皓(左耳朵耗子)(微博,博客)说:朋友圈很重要.一个人的朋友圈很重要,你在什么样的朋友圈,就会被什么样的朋友圈所影响. 因为<构建之法(电子版)>结识了人生好教练:周筠老师(知乎,微博, ...
最新文章
- 原理分析之:从JDBC到Mybatis
- 80C51单片机的最小系统
- 如果有一天,我们再见面
- 嵌入式成长轨迹34 【嵌入式学习阶段】【ARM环境调试】【QT 移植环境及简单程序示例】---补充《ok6410 Qt移植百科全书》...
- 基础概念总结(spring security、Quartz、JUnit测试)
- php的range函数
- java文件快速扫描仪_Java扫描仪具有示例的NextNextShort()方法
- 大场面试必问:秒杀90%Java面试者,后悔没有早点知道!
- java访问 mysql返回空格_JAVA连接数据库返回输出信息
- adams建立一绳索不带滑轮_Adams绳索实验
- 安全浏览器版本过低?该升级浏览器内核了
- GroupBox与Panel控件
- .net微信 验证 Token完整代码
- 如何评价吴军《浪潮之巅》?来自反面的声音
- 【嵌入式20】STM32F103完成对SD卡的数据读取详细操作
- 密码学——Schnorr签名算法
- “记忆力争夺战”走向尾声,“潜意识记忆营销”将成破局利器
- 全民一起玩Python基础篇第六课:复杂结构初步(列表、对象、模块等)(下)
- 计算机如何卸载应用程序,如何卸载电脑程序,详细教您电脑怎么卸载软件程序...
- win10系统相机灰色问题解决(如腾讯会议中开启失败)
热门文章
- perl学习笔记-----------------------(8)
- GitHub 中超过3.5万开源代码被投毒
- 最新版华美淘客商城淘宝客程序源码
- iOS中 断点下载详解
- 承包一座山能做什么_您为什么没有得到最好的承包商,又能做些什么(第2部分)...
- 读易[2]·该出手时就出手(乾卦)
- Open the World 丨 COSCon'22志愿者招募正式启动
- 西游记中唐僧禅心坚定不好女色
- Mathematica仿真竞争性Lotka-Volterra方程(3种群)
- Ant Design Pro从零到一(认识AntD)