2018-2019-20175205實驗二面向對象程序設計《Java開發環境的熟悉》實驗報告

2018-2019-20175205實驗二面向對象程序設計《Java開發環境的熟悉》實驗報告

實驗要求

  • 沒有Linux基礎的同窗建議先學習《Linux基礎入門(新版)》《Vim編輯器》 課程
  • 完成實驗、撰寫實驗報告,實驗報告以博客方式發表在博客園,注意實驗報告重點是運行結果,遇到的問題(工具查找,安裝,使用,程序的編輯,調試,運行等)、解決辦法(空洞的方法如「查網絡」、「問同窗」、「看書」等一概得0分)以及分析(從中能夠獲得什麼啓示,有什麼收穫,教訓等)。報告能夠參考範飛龍老師的指導
  • 嚴禁抄襲,有該行爲者實驗成績歸零,並附加其餘懲罰措施。
  • 請你們先在實驗樓中的~/Code目錄中用本身的學號創建一個目錄,代碼和UML圖要放到這個目錄中,截圖中沒有學號的會要求重作,而後跟着下面的步驟練習。

實驗步驟

(一)單元測試

  • 三種代碼
    • 僞代碼:將問題抽象出來,寫出須要計算機執行的步驟
    • 產品代碼:用特定的編程語言翻譯
    • 測試代碼:測試代碼有沒有問題
  • 單元測試:對類實現的測試
    • 點擊New->Directory新建一個test目錄,再右鍵點擊設置環境變量,選擇Mark Directory->Test Sources Root便可

  • 設計一個測試用例:將正常狀況,異常狀況,邊界狀況一一排查,檢查出全部bug並修改,才能保證所寫代碼比較健全準確
    • 正常狀況
      html

    • 邊界狀況:通常容易遺漏邊界狀況,並且容易出錯
      java

    • 異常狀況 ->依據所出現的異常狀況,就應該針對此問題修改源代碼,直至測試成功。
      git

(二)以 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:\Users\13015\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-1\171.4073.35\lib\junit.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字節的空緩衝區。
    app

  • 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不存在

相關文章
相關標籤/搜索