天天看點

JavaWeb - Junit 反射&注解

Junit單元測試:

  1. 測試的分類:(測試就是對所完成功能的校驗,檢視功能是否有缺陷有漏洞。在工作中,每次做完功能後都要進行測試,測試通過才可以結束該功能的編寫。測試是開發中很重要的一部分。)
    1. 黑盒測試:不需要寫代碼,給輸入值,看程式是否能夠輸出期望的值。
    2. 白盒測試:需要寫代碼。關注程式具體的執行流程。
  2. Junit使用:白盒測試的一種
    • 使用的步驟:
      1. 定義一個測試類(測試用例)
        • 建議:
          • 測試類名:被測試的類名Test 例如:CalculatorTest
          • 包名:xxx.xxx.xx.test cn.itcast.test
      2. 定義測試方法:可以獨立運作
        • 建議:
          • 方法名:test測試的方法名 testAdd()
          • 傳回值:void
          • 參數清單:空參【 傳回值的類型是void 和 參數清單 為空參的原因就是沒有其他的方法會調用 也不會調用其他方法 不需要參數和傳回值】
      3. 給方法加@Test 注解
      4. 導入junit依賴環境
      5. 判定結果: 使用Junit來測試不好使用輸出的值來判斷是否是成功。
        • 一般是通過執行結果的顔色來判斷。
          • 紅色:失敗
          • 綠色:成功
        • 或者我們會使用斷言操作來處理結果
          • Assert.assertEquals(期望的結果,運算的結果);
    • 補充:
      • @Before

        : 修飾的方法會在測試方法之前被自動執行 注意的是@Before不止運作一次,它會在每個用例運作之前都運作一次 主要用于一些獨立于用例之間的準備工作
      • @After

        : 修飾的方法會在測試方法執行之後自動被執行 同樣的@After不止運作一次,它會在每個用例運作之後都運作一次 主要用于一些獨立于用例之間的準備工作
      • @BeforeClass

        : 當我們運作幾個有關聯的用例時,可能會在資料準備或其它前期準備中執行一些相同的指令,這個時候為了讓代碼更清晰,更少備援,可以将公用的部分提取出來,放在一個方法裡,并為這個方法注解@BeforeClass。意思是在測試類裡所有用例運作之前,運作一次這個方法。例如建立資料庫連接配接、讀取檔案等。注意:方法名可以任意,但必須是public static 這個方法隻會運作一次
      • @AfterClass

        :@BeforeClass對應,在測試類裡所有用例運作之後,運作一次。用于處理一些測試後續工作
      • @Ignore

        :有時候我們想暫時不運作某些測試方法\測試類,可以在方法前加上這個注解 (但是不建議使用這個注解)
      • @Runwith

        :進行運作器的修改(不添加此注解使用預設的運作器)如以後常見一的一種運作器 就是junit 和 Spring的整合 :

        @RunWith(SpringJUnit4ClassRunner.class)

    • JUnit4的單元測試用例執行順序為:

      @BeforeClass -> @Before -> @Test -> @After -> @AfterClass

      每一個測試方法的調用順序為:

      @Before -> @Test -> @After

      (常見的面試題)

反射:架構設計的靈魂

  1. 架構:半成品軟體。可以在架構的基礎上進行軟體開發,簡化編碼 降低耦合 提高代碼的複用性。【使用架構的好處非常的多 這裡隻是簡單的提一下】
  2. 反射:将類的各個組成部分封裝為其他對象,這就是反射機制
    • 使用反射的好處:

      1. 可以在程式運作過程中,操作這些對象。

      2. 可以解耦,提高程式的可擴充性。

    • 擷取Class對象的三種方式:
      1. Class.forName(“全限定類名”):将位元組碼檔案加載進記憶體,傳回Class對象【全類名: 包名 + 類名 】
        • 多用于配置檔案,将類名定義在配置檔案中。讀取檔案,加載類 也是最常用的方法。
      2. 類名.class:通過類名的屬性class擷取
        • 多用于參數的傳遞 但是需要導包 否則就會出現錯誤 依賴性太強(不常使用)
      3. 對象.getClass():getClass()方法在Object類中定義着。
        • 多用于對象的擷取位元組碼的方式 已經有了對象 這樣的方式就不好用。
      • 結論:

        同一個位元組碼檔案(*.class)在一次程式運作過程中,隻會被加載一次,不論通過哪一種方式擷取的Class對象都是同一個。

    • Class對象功能:
      • 擷取功能:
        1. 擷取成員變量們
          • Field[] getFields() :擷取所有public修飾的成員變量
          • Field getField(String name) 擷取指定名稱的 public修飾的成員變量 傳入的是變量的名稱。
          • Field[] getDeclaredFields() 擷取所有的成員變量,不考慮修飾符 即使是私有的也是能夠擷取的。
          • Field getDeclaredField(String name) 擷取指定名稱的成員變量 不考慮修飾符,傳入的是變量的名稱。
        2. 擷取構造方法們
          • Constructor<?>[] getConstructors()
          • Constructor getConstructor(類<?>… parameterTypes) 傳入的參數是屬性的位元組碼檔案
          • Constructor getDeclaredConstructor(類<?>… parameterTypes)
          • Constructor<?>[] getDeclaredConstructors()
          • 方法中參數的類型是:構造方法中參數的class對象。
        3. 擷取成員方法們:
          • Method[] getMethods()
          • Method getMethod(String name, 類<?>… parameterTypes)
          • Method[] getDeclaredMethods()
          • Method getDeclaredMethod(String name, 類<?>… parameterTypes)
          • 參數是:方法的名稱,參數的class對象。
        4. 擷取類名
          • String getName() 擷取的是全限定類名
          • String getSingleName() 擷取的是類名
    • 其他對象的使用:
      • Field:成員變量
        • 操作:
          1. 設定值
            • void set(Object obj, Object value)
          2. 擷取值
            • get(Object obj)
          3. 忽略通路權限修飾符的安全檢查【常用】
            • setAccessible(true):暴力反射(暴力反射使用的時機就是:使用private進行屬性的修飾的時候)
      • Constructor:構造方法
        • 建立對象:
          • T newInstance(Object… initargs) :傳入的是對象初始化需要的參數
          • 在使用反射來擷取相應的構造器時,出現這樣的錯誤是沒有相應的構造方法(傳入的參數和構造方法中的參數不一緻)

            java.lang.NoSuchMethodException: cn.itwang.reflect.domain.Preson.(int, java.lang.String)

          • 如果使用空參數構造方法建立對象,操作可以簡化:Class對象的newInstance方法,不需要傳遞參數。
      • Method:方法對象
        • 執行方法:
          • Object invoke(Object obj, Object… args) 傳入的是方法執行所需要的參數
        • 擷取方法名稱:
          • String getName:擷取方法名

注解:

  1. 概念:注解是用來說明程式的,是給計算機看的
    • 注釋:用文字描述程式的。給程式員看的
    • 定義:注解(Annotation),也叫中繼資料。一種代碼級别的說明。它是JDK1.5及以後版本引入的一個特性,與類、接口、枚舉是在同一個層次。它可以聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,注釋。
    • 通過反編譯 可以知道注解就是一個接口
      • 概念描述:
      • JDK1.5之後的新特性
      • 說明程式的
      • 使用注解:@注解名稱
    • 注解的作用主要是分為三類:
      • 編寫文檔:通過代碼裡辨別的注解生成文檔【生成文檔doc文檔】通過 javadoc指令
      • 代碼分析:通過代碼裡辨別的注解對代碼進行分析【使用反射】我們主要就是用這個功能
      • 編譯檢查:通過代碼裡辨別的注解讓編譯器能夠實作基本的編譯檢查【Override】
    • JDK中預定義的一些注解
      • @Override :檢測被該注解标注的方法是否是繼承自父類(接口)的 例如 toString()方法。
      • @Deprecated:該注解标注的内容,表示已過時,但是不表示不能使用 例如 Date 中的getMonth 方法。
      • @SuppressWarnings:壓制警告 需要傳遞參數。
        • 一般傳遞參數all @SuppressWarnings(“all”)
    • 自定義注解
      • 格式:
        @元注解
        public @interface 注解名稱{
        	屬性清單;
        }
                   
        public @interface StudentsAnnotation {
        	public String name();
        	int age() default 18;
        	int[] array();
        }
                   
      • 本質:注解本質上就是一個接口,該接口預設繼承Annotation接口 通過javap 反編譯來得知。
        • public interface MyAnno extends java.lang.annotation.Annotation {}
      • 屬性:接口中的抽象方法(“無形參的方法”)
        • 要求:
          • 屬性的傳回值類型有下列取值
            • 基本資料類型
            • String
            • 枚舉
            • 注解
            • 以上類型的數組
          • 定義了屬性,在使用時需要給屬性指派
            • 如果定義屬性時,使用default關鍵字給屬性預設初始化值,則使用注解時,可以不進行屬性的指派。
            • 如果隻有一個屬性需要指派,并且屬性的名稱是value,則value可以省略,直接定義值即可。例如SuppressWarnings’中
            • 數組指派時,值使用{}包裹。如果數組中隻有一個值,則{}可以省略
      • 元注解:用于描述注解的注解
        • @Target:描述注解能夠作用的位置
          • ElementType取值:
            • TYPE:可以作用于類上
            • METHOD:可以作用于方法上
            • FIELD:可以作用于成員變量上
        • @Retention:描述注解被保留的階段
          • @Retention(RetentionPolicy.RUNTIME):目前被描述的注解,會保留到class位元組碼檔案中,并被JVM讀取到
        • @Documented:描述注解是否被抽取到api文檔中
        • @Inherited:描述注解是否被子類繼承
    • 在程式使用(解析)注解:擷取注解中定義的屬性值
      1. 擷取注解定義的位置的對象 (Class,Method, Field)
      2. 擷取指定的注解的方法
        • getAnnotation(Class)
          //其實就是在記憶體中生成了一個該注解接口的子類實作對象
          public class ProImpl implements Pro{
             public String className(){
                  return "cn.itcast.annotation.Demo1";
              }
              public String methodName(){
                  return "show";
              }
          }
                     
      3. 調用注解中的抽象方法擷取配置的屬性值

繼續閱讀