2018-2019-2 20175227张雪莹《Java程序设计》 实验二《Java面向对象程序设计》
2018-2019-2 20175227张雪莹《Java程序设计》
实验二《Java面向对象程序设计》
实验报告封面
- 课程:Java程序设计 班级:1752班 姓名:张雪莹 学号:20175227
- 指导教师:娄嘉鹏 实验日期:2019年4月13日
- 实验时间:--- 实验序号:实验二
- 实验名称:Java开发环境的熟悉
- 实验题目:
- 实验要求:
- 完成实验二《Java面向对象程序设计》中的内容
- 其中Eclipse相关的内容参考Intellj IDEA 简易教程换成IDEA实现
- 参考实验二《Java面向对象程序设计》的一点说明,完成云班课中的检查点,也可以先完成实验报告,直接提交。注意不能只有截图,要有知识点,原理,遇到的问题和解决过程等说明。实验报告中一个检查点要有多张截图。
- 发表实验报告博客,标题“学期(如2018-2019-2) 学号(如20175300)实验二《Java面向对象程序设计》实验报告”
实验步骤
单元测试
我们在IDEA中建一个项目,输入图中代码:
针对
MyUtil
类我们写一个MyUtilTest.java
的测试模块,如图:
在 IDEA中我们把产品代码放在src目录中,把测试代码放在test目录中,右键单击项目,在弹出的菜单中选择New->Directory新建一个目录并输入目录名test。右键单击test目录,在弹出的菜单中选择Mark Directory as->Test Sources Root:
在IDEA中运行结果如下,测试结果符合预期:
只有一组输入的测试是不充分的,把一般情况都测试一下,代码如图。运行结果如图,测试结果符合预期:
不能只测试正常情况,下面看看异常情况如何,比如输入为负分或大于100的成绩,代码如图:
运行程序发现负分时与期望不一致,原因是判断不及格时没有要求成绩大于零。修改MyUtil.java,增加对负分的判断,再次运行测试,结果符合预期:
输入为“0,60,70,80,90,100”这些边界情况进行测试如下:
边界情况中输入100时有一个Bug,修改程序后所有结果符合预期
TDD(Test Driven Devlopment, 测试驱动开发)
一般步骤
- 明确当前要完成的功能,记录成一个测试列表
- 快速完成编写针对此功能的测试用例
- 测试代码编译不通过(没产品代码呢)
- 编写产品代码
- 测试通过
- 对代码进行重构,并保证测试通过(重构下次实验练习)
- 循环完成所有功能的开发
设置好
JUnit
后,在IDEA中新建一个项目,然后新建一个空类MyUtil_1
:
鼠标单击类名会出现一个灯泡状图标,单击图标或按
Alt + Entert
,在弹出的菜单中选择Create Test
,并选择创建JUnit3的测试用例 :
- 增加第一个测试用例
testNormal
,注意测试用例前一定要有注解@Test,测试用例方法名任意,输入以下代码:
import org.junit.Test;
import junit.framework.TestCase;
public class MyUtilTest extends TestCase {
@Test
public void testNormal() {
assertEquals("不及格", MyUtil.percentage2fivegrade(55));
assertEquals("及格", MyUtil.percentage2fivegrade(65));
assertEquals("中等", MyUtil.percentage2fivegrade(75));
assertEquals("良好", MyUtil.percentage2fivegrade(85));
assertEquals("优秀", MyUtil.percentage2fivegrade(95));
}
}
- 测试结果出现了一个红条(red bar),说明测试没通过:
- 测试代码第十行传入55时,期望结果是“不及格”,代码返回了“错误”,修改
MyUtil.Java
吧,输入以下代码,再运行测试,如下图所示:
- 增加一个测试异常情况的用例testException和一个测试边界情况的用例testBoundary,如下图:
StringBuffer
类- 通过下图例子学习该类方法
- 通过下图例子学习该类方法
capacity返回的是目前的最大容量。length()返回的是字符串的长度。
String类和StringBuffer类的区别
- String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间。
- StringBuffer和StringBuilder类功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。对于经常要改变值的字符串应该使用StringBuffer和StringBuilder类。
- 一般情况下,速度从快到慢:StringBuilder>StringBuffer>String,这种比较是相对的,不是绝对的。
- 用法总结
- 如果要操作少量的数据用 = String
- 单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
- 多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
面对对象程序设计
- 三种代码
- 伪代码(自然语言)
- 产品代码
- 测试代码
- 面向对象三要素
- 抽象(去粗取精、化繁为简、由表及里、异中求同)
- 过程抽象
- 数据抽象
- 封装、继承与多态
- 继承:将若干个相同类中重复的方法用父类描述,若干类继承方法并重写方法即可
- 多态(面向对象程序设计的灵活性和可扩展性的基础):将若干个相同类中可以抽象出来的方法定义一个抽象方法
- 抽象(去粗取精、化繁为简、由表及里、异中求同)
- 三种代码
设计模式初步
- S.O.L.I.D原则
- SRP(Single Responsibility Principle,单一职责原则):决不要有一个以上的理由修改一个类
- OCP(Open-Closed Principle,开放-封闭原则):软件实体(类,模块,函数等)应该对扩充开放,对修改封闭。
- LSP(Liskov Substitusion Principle,Liskov替换原则)
- 子类必须可以被其基类所代
- 使用指向基类的指针或引用的函数,必须能够在不知道具体派生类对象类型的情况下使用它
- ISP(Interface Segregation Principle,接口分离原则):客户不应该依赖他们并未使用的接口
- DIP(Dependency Inversion Principle,依赖倒置原则)
- 高层模块不应该依赖于低层模块。二者都应该依赖于抽象
- 抽象不应该依赖于细节。细节应该依赖于抽象
- 模式与设计模式
- 设计模式有四个基本要素:
- Pattern name:描述模式,便于交流,存档
- Problem:描述何处应用该模式
- Solution:描述一个设计的组成元素,不针对特例
- Consequence:应用该模式的结果和权衡(trade-offs)
- 设计模式有四个基本要素:
- 其他面对对象原则
- "组合替代继承":这是说相对于继承,要更倾向于使用组合;
- "笛米特法则":这是说"你的类对其它类知道的越少越好";
- "共同封闭原则":这是说"相关类应该打包在一起";
- "稳定抽象原则":这是说"类越稳定,越应该由抽象类组成";
- S.O.L.I.D原则
练习
- 题目一:对设计模式示例进行扩充,体会OCP原则和DIP原则的应用,初步理解设计模式。让系统支持Boolean类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
- 产品代码为:
- 题目一:对设计模式示例进行扩充,体会OCP原则和DIP原则的应用,初步理解设计模式。让系统支持Boolean类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
// Server Classes
abstract class Data {
abstract public void DisplayValue();
}
class Integer extends Data {
int value;
Integer() {
value=100;
}
public void DisplayValue(){
System.out.println (value);
}
}
class Boolean extends Data {
boolean value;
Boolean(){
value=true;
}
public void DisplayValue(){
System.out.println(value);
}
}
abstract class Factory {
abstract public Data CreateDataObject();
}
class IntFactory extends Factory {
public Data CreateDataObject(){
return new Integer();
}
}
class BooFactory extends Factory {
public Data CreateDataObject(){
return new Boolean();
}
}
class Document {
Data pd;
Document(Factory pf){
pd = pf.CreateDataObject();
}
public void DisplayData(){
pd.DisplayValue();
}
}
public class MyDoc {
static Document d;
static Document e;
public static void main(String[] args) {
e=new Document(new BooFactory());
e.DisplayData();
}
}
运行结果为:
题目二:
- 以TDD的方式开发一个复数类Complex,要求如下:
// 定义属性并生成getter,setter
double RealPart;
double ImagePart;
// 定义构造函数
public Complex()
public Complex(double R,double I)
//Override Object
public boolean equals(Object obj)
public String toString()
// 定义公有方法:加减乘除
Complex ComplexAdd(Complex a)
Complex ComplexSub(Complex a)
Complex ComplexMulti(Complex a)
Complex ComplexDiv(Complex a)
- 产品代码
public class Complex {
// 定义属性并生成getter,setter
double RealPart;
double ImagePart;
// 定义构造函数
public Complex(){}
public Complex(double R,double I){
ImagePart = I;
RealPart = R;
}
public boolean equals(Object obj){
if(this == obj) {
return true;
}
if(!(obj instanceof Complex)) {
return false;
}
Complex complex = (Complex) obj;
if(complex.RealPart != ((Complex) obj).RealPart) {
return false;
}
if(complex.ImagePart != ((Complex) obj).ImagePart) {
return false;
}
return true;
}
public String toString() {
String str = "";
if (ImagePart > 0)
str = RealPart + "+" + ImagePart + "i";
if (ImagePart == 0)
str = RealPart + "";
if (ImagePart < 0)
str = RealPart + " " + ImagePart + "i";
return str;
}
// 定义公有方法:加减乘除
Complex ComplexAdd(Complex a) {
return new Complex(RealPart+a.RealPart,ImagePart+a.ImagePart);
}
Complex ComplexSub(Complex a) {
return new Complex(RealPart-a.RealPart,ImagePart-a.ImagePart);
}
Complex ComplexMulti(Complex a) {
return new Complex(RealPart*a.RealPart,ImagePart*a.ImagePart);
}
Complex ComplexDiv(Complex a) {
if(a.RealPart==0||a.ImagePart==0) {
System.out.println("被减数不能为0");
return new Complex();
}
double d = Math.sqrt(a.RealPart*a.RealPart)+Math.sqrt(a.ImagePart*a.ImagePart);
return new Complex((RealPart*a.RealPart+ImagePart*a.ImagePart)/d,Math.round((RealPart*a.ImagePart-ImagePart*a.RealPart)/d));
}
}
- 测试代码
import static org.junit.Assert.*;
import org.junit.Test;
import junit.framework.TestCase;
public class ComplexTest extends TestCase {
Complex complex = new Complex(1,1);
@Test
public void testAdd(){
assertEquals(new Complex(3.3,3.4), complex.ComplexAdd(new Complex(2.3,2.4)));
}
//测试加法
@Test
public void testSub(){
assertEquals(new Complex(-5.3,-2.4), complex.ComplexSub(new Complex(6.3,3.4)));
}
//测试减法
@Test
public void testMulti(){
assertEquals(new Complex(3.0,2.0), complex.ComplexMulti(new Complex(3.0,2.0)));
}
//测试乘法
@Test
public void testDiv(){
assertEquals(new Complex(1.0,1.0), complex.ComplexDiv(new Complex(1.0,1.0)));
assertEquals(new Complex(0.0,0.0), complex.ComplexDiv(new Complex(1.0,0.0)));
//assertEquals(new Complex(0.0,0.0), complex.ComplexDiv(new Complex(3,4)));
//边缘测试
}
@Test
public void testequals(){
assertEquals(true, complex.equals(new Complex(1.0,1.0)));
}
//测试判断相等
}
- 运行结果
- 题目三:
- 对实验二中的代码进行建模,发类图的截图
- 对实验二中的代码进行建模,发类图的截图
实验中遇到的问题和解决过程
- 问题1:JUnit测试时,Junit是红色的,如下图:
自己再网络上找的方法,试着清除缓存,重新导入包都无济于事
问题1解决方法:后来通过寻求同学帮助,在该同学博客中找到了解决办法,如下:
File -> Project Struct... -> Libraies -> 点击绿色的加号 -> Java -> 找到 IDEA 安装路径下的 Lib 中的junit-4.12 ->点击OK
问题2:在将
junit-4.12.jar
设置完成后,TestCase
仍是红色的问题2解决办法:在IDEA中选择菜单
File->Project Structure...
,在弹出的对话框中选择Dependancies
标签页,单击+号,选择JARs or Directories...
,输入上面找到的junit.jar
。
感悟和收获
- 一个程序的编写要有完整的生产过程:伪代码->产品代码->测试代码
- 要编写好的程序要遵守很多设计原则,以使得程序有逻辑清晰、简明扼要等符合设计原则的优点
- 在代码调试过程中遇到问题时,不仅可以上网寻求答案,与同学们讨论问题原因,借鉴同学做法,是更好的提高学习能力和掌握知识水平的好办法
参考资料
2018-2019-2 20175227张雪莹《Java程序设计》 实验二《Java面向对象程序设计》的更多相关文章
- 2018-2019-2 20175227张雪莹《Java程序设计》实验三 《敏捷开发与XP实践》
2018-2019-2 20175227张雪莹<Java程序设计> 实验三 <敏捷开发与XP实践> 实验报告封面 课程:Java程序设计 班级:1752班 姓名:张雪莹 学号: ...
- 2018-2019-2 20175227张雪莹 《Java程序设计》 实验一 Java开发环境的熟悉
2018-2019-2 20175227张雪莹<Java程序设计> 实验一 Java开发环境的熟悉 一.实验报告封面 课程:Java程序设计 班级:1752班 姓名:张雪莹 学号:2017 ...
- 2018-2019-2 20175227张雪莹《Java程序设计》实验五 《网络编程与安全》
2018-2019-2 20175227张雪莹<Java程序设计> 实验五 <网络编程与安全> 实验报告封面 课程:Java程序设计 班级:1752班 姓名:张雪莹 学号:20 ...
- 2018-2019-2 20175227张雪莹《Java程序设计》实验四 《Android程序设计》
2018-2019-2 20175227张雪莹<Java程序设计> 实验四 <Android程序设计> 实验报告封面 课程:Java程序设计 班级:1752班 姓名:张雪莹 学 ...
- 20175227张雪莹 2018-2019-2 《Java程序设计》第九周学习总结
20175227张雪莹 2018-2019-2 <Java程序设计>第九周学习总结 教材学习内容总结 第十一章 JDBC数据库操作 MySQL数据库管理系统 下载安装MySQL 若下载的是 ...
- 20175227张雪莹 2018-2019-2 《Java程序设计》第八周学习总结
20175227张雪莹 2018-2019-2 <Java程序设计>第八周学习总结 教材学习内容总结 第十五章 泛型与集合框架 泛型:主要目的是可以建立具有类型安全的集合框架,如链表.散列 ...
- 20175227张雪莹 2018-2019-2 《Java程序设计》第六周学习总结
20175227张雪莹 2018-2019-2 <Java程序设计>第六周学习总结 教材学习内容总结 第七章 内部类与异常类 内部类:在一个类中定义另一个类:包含内部类的类为外嵌类 内部类 ...
- 20175227张雪莹 2018-2019-2 《Java程序设计》第五周学习总结
20175227张雪莹 2018-2019-2 <Java程序设计>第五周学习总结 教材学习内容总结 第六章接口与实现 接口 接口体中所有的常量访问权限一定是public和static(可 ...
- 20175227张雪莹 2018-2019-2 《Java程序设计》第四周学习总结
20175227张雪莹 2018-2019-2 <Java程序设计>第四周学习总结 教材学习内容总结 一.子类和父类. 1.子类只继承父类中的protected和public访问权限的成员 ...
随机推荐
- oracle的PDB启动
/*以管理员身份登录*/sqlplus / as sysdba /*查看CDB的状态*/select status from v$instance; /*开启startup,默认是open*/star ...
- QTCPSOCKET 客户端已连接 而服务器无响应
最近在使用qt coding一个项目时,使用到了qtcpsocket模块来编写客户端与服务器.在windows平台下还能正常工作,但是在ubuntu平台下,客户端提示已连接时,服务器却没有响应.经过排 ...
- time模块(时间)
time.time() #返回当前时间的时间戳 time.sleep() #CPU休息时间 print(time.clock()) #计算CPU执行时间 time.gmtime() #结构化时间 UT ...
- entrySet用法 以及遍历map的用法
entrySet用法 以及遍历map的用法 keySet是键的集合,Set里面的类型即key的类型entrySet是 键-值 对的集合,Set里面的类型是Map.Entry 1.keySet( ...
- easyui-tree-url-param
远古写法 url后面加参数?param1=1¶m2=2 动态添加 onBeforeLoad: function (node, param) { param.param1= 1, par ...
- NSArray NSMutableArray
NSArray 或者 NSMUtableArray 去除重复的数据: 原来集合操作可以通过valueForKeyPath来实现的,去重可以一行代码实现: [array valueForKeyPath: ...
- python标准库之random模块
Python中的random模块用于生成随机数. 下面具体介绍random模块的功能: 1.random.random() #用于生成一个0到1的 随机浮点数:0<= n < 1.0 1 ...
- MFC中关于运行时类信息及动态创建对象的两个宏的意义(转)
http://blog.csdn.net/ligand/article/details/49839507 MFC运行时类信息 用途: 程序在运行时,获取对象类的信息及类的继承关系 实现: 1.定义的类 ...
- Visual C++ 6.0中if..else..的简单用法和基本格式
# include <stdio.h> int main (void) { float score; printf("请输入您的考试成绩:"); scanf(" ...
- es6学习笔记-Proxy、Reflect、Promise
Proxy Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程. Proxy 可以理解成,在目标对象之前 ...