• 2018-2019-20175205实验二面向对象程序设计《Java开发环境的熟悉》实验报告


    2018-2019-20175205实验二面向对象程序设计《Java开发环境的熟悉》实验报告

    实验要求

    • 没有Linux基础的同学建议先学习《Linux基础入门(新版)》《Vim编辑器》 课程
    • 完成实验、撰写实验报告,实验报告以博客方式发表在博客园,注意实验报告重点是运行结果,遇到的问题(工具查找,安装,使用,程序的编辑,调试,运行等)、解决办法(空洞的方法如“查网络”、“问同学”、“看书”等一律得0分)以及分析(从中可以得到什么启示,有什么收获,教训等)。报告可以参考范飞龙老师的指导
    • 严禁抄袭,有该行为者实验成绩归零,并附加其他惩罚措施。
    • 请大家先在实验楼中的~/Code目录中用自己的学号建立一个目录,代码和UML图要放到这个目录中,截图中没有学号的会要求重做,然后跟着下面的步骤练习。

    实验步骤

    (一)单元测试

    • 三种代码
      • 伪代码:将问题抽象出来,写出需要计算机执行的步骤
      • 产品代码:用特定的编程语言翻译
      • 测试代码:测试代码有没有问题
    • 单元测试:对类实现的测试
      • 点击New->Directory新建一个test目录,再右键点击设置环境变量,选择Mark Directory->Test Sources Root即可

    • 设计一个测试用例:将正常情况,异常情况,边界情况一一排查,检查出所有bug并修改,才能保证所写代码比较健全准确

      • 正常情况

      • 边界情况:一般容易遗漏边界情况,而且容易出错

      • 异常情况 ->依据所出现的异常情况,就应该针对此问题修改源代码,直至测试成功。

    (二)以 TDD的方式研究学习StringBuffer

    - TDD(Test Driven Devlopment, 测试驱动开发):先写测试代码,再写产品代码。
    • 步骤:
      • 明确当前要完成的功能,记录成一个测试列表
      • 快速完成编写针对此功能的测试用例
      • 测试代码编译不通过(没产品代码呢)
      • 编写产品代码
      • 测试通过
      • 对代码进行重构,并保证测试通过(重构下次实验练习)
      • 循环完成所有功能的开发
    • 安装JUnit插件

    • 下载完成后,在IDEA中新建空类,鼠标单击类名会出现一个灯泡状图标,单击图标或按Alt + Enter,在弹出的菜单中选择Create Test

    • 选择创建JUnit3的测试用例

      • 如果TestCase是红色的,需要在IDEA中的项目(模块)中加入junit.jar包,junit.jar包的位置可以在Everything中查找
      • 在弹出的对话框中选择Dependancies标签页,单击+号,选择JARs or Directories...,输入上面找到的C:Users13015AppDataLocalJetBrainsToolboxappsIDEA-Uch-1171.4073.35libjunit.jar
    StringBuffer
    • capacity返回的是目前的最大容量而length返回的是字符串长度

      • 默认值为16
      • 根据capacity的构造方法,可以指定初始容量
    • charAt返回该位置上的字符

    • indexOf返回第一次出现的指定子字符串在该字符串中的索引

    StringBuilder、StringBuffer、String类之间的关系
    • String类:String的值是不可变的,因此每次对String操作都会生成新的String对象,浪费大量内存空间。为理解这个,我从书上摘取了一个小栗子~a最后指向56EF,但最后12AB和56EF地址中的数据仍然存在,因此String的操作都是改变赋值地址而不是改变值操作。
      String a = "你好"
      a = "boy"
      a = "12.97"

    • StringBuffer是可变类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量,非常人性化。
      StringBuffer buf=new StringBuffer(); //分配默认长16字节的字符缓冲区
      StringBuffer buf=new StringBuffer(512); //分配长512字节的字符缓冲区
      StringBuffer buf=new StringBuffer("this is a test")//在缓冲区中存放了字符串,并在后面预留了16字节的空缓冲区。

    • StringBuilder与StringBuffer功能基本相似,主要区别在于StringBuffer类的方法是多线程、安全的,而StringBuilder不是线程安全的,相比而言,StringBuilder类会略微快一点。

      • 多线程:每一个任务称为一个线程。可以同时运行一个以上线程的程序称为多线程程序。
    • 总结

      • String:适用于少量的字符串操作的情况
      • StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
      • StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况

    (三)面向对象三要素

    • 抽象:抽出事物的本质特征而暂不考虑细节,对于复杂的问题分层求解
      • 过程抽象:结果是函数
      • 数据抽象:结果是抽象数据类型
    • 封装,继承与多态(面向对象的三要素)
      • 封装:将数据与相关行为包装在一起以实现信息隐藏,java中使用类进行封装,接口是封装准确描述手段
      • 继承:关键在于确认子类为父类的一个特殊类型,以封装为基础,继承可以实现代码复用,继承更重要的作用是实现多态。
      • 多态:同一消息可以根据发送对象的不同而采用多种不同的行为方式

    (四)设计模式初步

    • 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)

    (五)练习

    • 练习题目1:让系统支持Double类,并在MyDoc类中添加测试代码表明添加正确,提交测试代码和运行结的截图,加上学号水印
      • 产品代码
    // Sever Classer
    abstract class Data{
        public abstract void DisplayValue();
    }
    class Integer extends Data{
        int value;
        Integer(){
            value = 100;
        }
        public void DisplayValue(){
            System.out.println(value);
        }
    }
    class Double extends Data{
        double value;
        Double(){
            value = 5.0;
        }
        public void DisplayValue(){
            System.out.println(value);
        }
    }
    // Pattern Classes
    abstract class Factory{
         public abstract Data CreateDataObject();
    }
    class IntFactory extends Factory{
        public Data CreateDataObject(){
            return new Integer();
        }
    }
    class DoubleFactory extends Factory{
        public Data CreateDataObject(){
            return new Double();
        }
    }
    //Client classes
    class Document {
        Data pd;
        Document(Factory pf){
            pd = pf.CreateDataObject();
        }
        public void DisplayData(){
            pd.DisplayValue();
        }
    }
    public class MyDoc {
        static Document d;
        static Document f;
        public static void main(String[] args) {
            d = new Document(new IntFactory());
            d.DisplayData();
            f = new Document(new DoubleFactory());
            f.DisplayData();
        }
    }
    
    • 运行结果

    • 练习题目2:以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 MyComplex{
        //定义属性并生成getter,setter
        private double realPart;
        private double imagePart;
        public double getRealPart(){
            return realPart;
        }
        public double getImagePart(){
            return imagePart;
        }
    
        //定义构造函数
        public MyComplex(){}
        public MyComplex(double r,double i){
            realPart = r;
            imagePart = i;
        }
        //Override Object
        @Override
        public boolean equals(Object obj){
            if(this == obj){
                return true;
            }
            if(!(obj instanceof MyComplex)) {
                return false;
            }
            MyComplex complex = (MyComplex) obj;
            if(complex.realPart != ((MyComplex) obj).realPart) {
                return false;
            }
            if(complex.imagePart != ((MyComplex) obj).imagePart) {
                return false;
            }
            return true;
        }
        @Override
        public String toString(){
            String s = new String();
            if(imagePart >0 && realPart!=0){
                s = ""+getRealPart()+"+"+getImagePart()+"i";
            }
            if(imagePart >0 && realPart==0){
                s= getImagePart()+"i";
            }
            if(imagePart <0 &&realPart!=0)
            {
                s = ""+getRealPart()+getImagePart()+"i";
            }
            if(imagePart <0 && realPart==0){
                s= getImagePart()+"i";
            }
            if(imagePart ==0 &&realPart!=0)
            {
                s = ""+getRealPart();
            }
            if(imagePart ==0 && realPart==0){
                s= "0";
            }
            return s;
        }
        //定义公有方法:加减乘除
        public MyComplex complexAdd(MyComplex a){
            return new MyComplex(realPart+a.realPart, imagePart +a.imagePart);
        }
        public MyComplex complexSub(MyComplex a){
            return new MyComplex(realPart-a.realPart, imagePart -a.imagePart);
        }
        public MyComplex complexMulti(MyComplex a){
            return new MyComplex(realPart * a.realPart - imagePart * a.imagePart, realPart * a.imagePart + imagePart * a.realPart);
        }
        public MyComplex complexDiv(MyComplex a){
            return new MyComplex((realPart * a.realPart + imagePart * a.imagePart) / (a.imagePart * a.imagePart + a.realPart * a.realPart), (imagePart * a.realPart - realPart * a.imagePart) / (a.realPart * a.realPart + a.realPart * a.realPart));
        }
    
    }
    
    
    • 测试代码
    import junit.framework.TestCase;
    import org.junit.Test;
    
    public class MyComplexTest extends TestCase {
        MyComplex a = new MyComplex(2.0,4.0);
        MyComplex b = new MyComplex(0.0,-3.0);
        MyComplex c = new MyComplex(-5.0,0.0);
        @Test
        public void testgetRealpart(){
            assertEquals(2.0,a.getRealPart());
            assertEquals(0.0,b.getRealPart());
            assertEquals(-5.0,c.getRealPart());
        }
        @Test
        public void testgetImagePart(){
            assertEquals(4.0,a.getImagePart());
            assertEquals(-3.0,b.getImagePart());
            assertEquals(0.0,c.getImagePart());
        }
        @Test
        public void testMyComplexAdd(){
            String q = a.complexAdd(b).toString();
            String w = b.complexAdd(c).toString();
            String e = c.complexAdd(a).toString();
            assertEquals("2.0+1.0i",q);
            assertEquals("-5.0-3.0i",w);
            assertEquals("-3.0+4.0i",e);
        }
        @Test
        public void testMyComplexSub(){
            String r = a.complexSub(b).toString();
            String t = b.complexSub(c).toString();
            String y = c.complexSub(a).toString();
            assertEquals("2.0+7.0i",r);
            assertEquals("5.0-3.0i",t);
            assertEquals("-7.0-4.0i",y);
        }
        @Test
        public void testMyComplexMulti(){
            String u = a.complexMulti(b).toString();
            String i = b.complexMulti(c).toString();
            String o = c.complexMulti(a).toString();
            assertEquals("12.0-6.0i",u);
            assertEquals("15.0i",i);
            assertEquals("-10.0-20.0i",o);
        }
        @Test
        public void testMyComplexDiv(){
            String p = c.complexDiv(a).toString();
            assertEquals("-0.5+2.5i",p);
        }
        @Test
        public void testtoString(){
            assertEquals("2.0+4.0i",a.toString());
            assertEquals("-3.0i",b.toString());
            assertEquals("-5.0",c.toString());
        }
    }
    
    • 运行结果

    实验中遇到的问题

    Q: junit 使用org.junit不存在,点到代码中红色的部分显示:Cannot resolve symbol 'junit'

    A:File -> Project Struct... -> Libraies -> 点击绿色的加号 -> Java -> 找到 IDEA 安装路径下的 Lib 中的junit-4.12 ->点击OK

    Q:在对append进行测试的时候,明明期望的值和实际值相同,但还是测试失败

    A:将StringBuffer转为字符串再比较,即可得出答案

    public void testappend() throws Exception{
            String q,w,e;
            a = a.append("abc");
            b = b.append("abc");
            c = c.append(ch,2,3);
            q = a.toString();
            w = b.toString();
            e = c.toString();
            assertEquals("StringBufferabc",q);
            assertEquals("StringBufferStringBufferabc",w);
            assertEquals("StringBufferStringBufferStringBufferc12",e);
        }
    
    • 单元测试的好处
      单元测试可以帮助我测试一些边界,异常情况,就比如说我的结对项目,运行完之后往往找不到出错点,有很多细节问题都没有考虑到代码中,这是通过单元测试检测出一些bug,因此可以对产品代码加以修改和补充,完善产品代码,写出更加健全符合要求的程序。

    参考博客

    org.junit不存在

  • 相关阅读:
    数据结构—链表
    python字母串查找基本操作
    python九九乘法表程序代码
    SpringMVC跨域问题排查以及源码实现
    深入理解MySql子查询IN的执行和优化
    Dubbo源码阅读-服务导出
    Disconf源码分析之启动过程分析下(2)
    Disconf源码分析之启动过程分析上(1)
    Java多线程volatile和synchronized总结
    Java多线程基础总结
  • 原文地址:https://www.cnblogs.com/orii/p/10695488.html
Copyright © 2020-2023  润新知