Junit單元測試棚放,反射枚粘,注解

一,Junit單元測試

測試分類:
黑盒測試(不需要寫代碼飘蚯,給輸入值馍迄,看程序是否能夠輸出期望的值)和白盒測試(需要寫代碼福也,關(guān)注程序具體的執(zhí)行流程)。
Junit使用步驟:
(1)定義一個測試類(測試用例)
建議:測試類名:被測試的類名Test攀圈;包名:xxx.xxx.xx.test
(2)定義測試方法:可以獨立運行
建議:方法名:test測試的方法名暴凑;返回值:void;參數(shù)列表:空參赘来。
(3)給方法加注解@Test
(4)導(dǎo)入Junit依賴
判定結(jié)果:
紅色:失斚衷;綠色:成功犬辰。
一般會使用斷言操作來處理結(jié)果

Assert.assertEquals(3,result);//期望結(jié)果嗦篱,斷言結(jié)果
 /**
     * 初始化方法:
     * 用于資源申請,所有測試方法在執(zhí)行之前都會先執(zhí)行該方法
     */
    @Before
    public void init(){
        System.out.println("init...");
    }

    /**
     * 釋放資源方法:
     * 用于在所有測試方法執(zhí)行完后幌缝,都會自動執(zhí)行該方法
     */
    @After
    public void close(){
        System.out.println("close...");
    }

二灸促,反射

是框架設(shè)計的靈魂。
定義:將類的各個組成部分封裝為其他對象狮腿,這就是反射機制腿宰。
好處:
(1)可以在程序運行過程中,操作這些對象缘厢。
(2)可以解耦吃度,提高程序的可擴展性。
獲取class對象的方式:
(1)Class.forName("全類名"):將字節(jié)碼文件加載進(jìn)內(nèi)存贴硫,返回Class對象椿每。
多用于配置文件,將類名定義在配置文件中英遭。讀取文件间护,加載類。
(2)類名.class:通過類名的屬性class獲取挖诸。
多用于參數(shù)的傳遞
(3)對象.getClass():getClass()方法在Object類中定義著汁尺。
多用于對象的獲取字節(jié)碼的方式

Class cls1 = Class.forName("cn.itcast.day12.demo01.test.Person");
        System.out.println(cls1);
        //(2)
        Class cls2 = Person.class;
        System.out.println(cls2);
        //(3)
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3);

結(jié)論:同一個字節(jié)碼文件(*.class)在一次程序運行過程中,只會被加載一次多律,不論通過哪一種方式獲取的Class對象都是同一個痴突。
Class對象功能:
獲取功能:獲取成員變量們,獲取構(gòu)造方法們狼荞,獲取成員方法們辽装,獲取類名。
Field[] getFields()獲取所有public修飾的成員變量相味;
Field getField(String name)獲取指定名稱的public修飾的成員變量拾积;

public static void main(String[] args) throws Exception {
        //0,獲取Person的Class對象
        Class personClass = Person.class;
        //1,獲取成員變量getFields(),getField(),getDeclaredFields(),getDeclaredField()
        Field[] fields = personClass.getFields();
        for(Field field : fields){
            System.out.println(field);
        }
        System.out.println("======");

        Field a = personClass.getField("a");
        //獲取成員變量a的值
        Person p = new Person();
        Object value = a.get(p);
        System.out.println(value);
        //設(shè)置成員變量a的值
        a.set(p,"張三");
        System.out.println(p);
        System.out.println("======");

        //Field[] getDeclaredFields():獲取所有的成員變量,不考慮修飾符
        Field[] declaredFields = personClass.getDeclaredFields();
        for(Field declareField : declaredFields){
            System.out.println(declareField);
        }
        //Fiels getDeclaredField(String name)
        Field ad = personClass.getDeclaredField("age");
        //忽略訪問權(quán)限修飾符的安全檢查
        ad.setAccessible(true);//暴力反射
        Object value2 = ad.get(p);
        System.out.println(value2);
    }

獲取構(gòu)造方法:

public static void main(String[] args) throws Exception {
        //0,獲取Person的Class對象
        Class personClass = Person.class;
        /**
         * 獲取構(gòu)造方法們
         */
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //創(chuàng)建對象
        Object person = constructor.newInstance("張三", 23);
        System.out.println(person);
        System.out.println("========");

        //使用空參構(gòu)造器
        Constructor constructor1 = personClass.getConstructor();
        System.out.println(constructor1);
        //創(chuàng)建對象
        Object person1 = constructor1.newInstance();
        System.out.println(person1);
        //空參構(gòu)造可以使用簡化形式直接用class對象的newInstance()方法
        Object o = personClass.newInstance();
        System.out.println(o);
    }

獲取成員方法們:
執(zhí)行方法:Object invoke(Object obj, Object... args)
獲取所有public修飾的方法:getMethods();
獲取方法名稱:String getName()

獲取類名:

     //0,獲取Person的Class對象
        Class personClass = Person.class;
        String className = personClass.getName();
        System.out.println(className);
    }

案例:寫一個框架,可以幫我們創(chuàng)建任意類的對象拓巧,并且執(zhí)行其中任意方法。
實現(xiàn):(1)配置文件(2)反射
步驟:
(1)將需要創(chuàng)建的對象的全類名和需要執(zhí)行的方法定義在配置文件中玲销;
(2)在程序中加載讀取配置文件
(3)使用反射技術(shù)來加載類文件進(jìn)內(nèi)存
(4)創(chuàng)建對象
(5)執(zhí)行方法
pro.properties文件:

className=cn.itcast.day12.demo01.test.Student
methodName=sleep
/**
 * 框架類
 */
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        /**
         * 前提:不能改變該類的任何代碼
         * 可以創(chuàng)建任意類的對象,可以執(zhí)行任意方法
         */
        //1,加載配置文件
        //1.1創(chuàng)建Properties對象
        Properties pro = new Properties();
        //1.2加載配置文件贤斜,轉(zhuǎn)換為一個集合
        //1.2.1獲取class目錄下的配置文件
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        pro.load(is);

        //2,獲取配置文件中定義的數(shù)據(jù)
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        //3瘩绒,加載該類進(jìn)內(nèi)存
        Class cls = Class.forName(className);

        //4,創(chuàng)建對象
        Object obj = cls.newInstance();

        //5,獲取方法對象
        Method method = cls.getMethod(methodName);

        //6,執(zhí)行方法
        method.invoke(obj);
    }
}

三锁荔,注解

概念:說明程序的,給計算機看的
JDK中預(yù)定義的一些注解:

  • @Override:檢測該注解標(biāo)注的方法是否是繼承自父類的
  • @Deprecated:該注解標(biāo)注的內(nèi)容表示已過時
  • @SuppressWarnings:壓制警告
    *一般傳遞參數(shù)all

自定義注解:
格式:元注解
public @interface 注解名稱{
屬性列表蝙砌;//其實就是成員方法
}
本質(zhì):注解本質(zhì)上就是一個接口阳堕,該接口默認(rèn)繼承Annotation接口
public interface MyAnno extends java.lang.annotation.Annotation{}
屬性:接口中的抽象方法

  • 屬性的返回值類型有下列取值:基本數(shù)據(jù)類型、字符串择克、枚舉恬总、注解、以上類型的數(shù)組肚邢。
  • 定義了屬性壹堰,在使用時需要給屬性賦值:如果定義屬性時,使用default關(guān)鍵字給屬性默認(rèn)初始值骡湖,則使用注解時贱纠,可以不進(jìn)行屬性的賦值;如果只有一個屬性需要賦值响蕴,并且屬性的名稱是value谆焊,則value可以省略,直接定義值即可浦夷;數(shù)組賦值時辖试,使用{}包裹,如果數(shù)組中只有一個值军拟,則大括號可以省略剃执。
public @interface MyAnno2 {
    int age();
}
@MyAnno2(age = 12)
public class DemoAnnotation {
}

枚舉

public enum Person {
    p1,p2;
}
public @interface MyAnno {  
    Person per();
}
@MyAnno(per = Person.p1)
public class Worker {
}

所有屬性賦值:

public @interface MyAnno {
    Person per();
    MyAnno2 anno2();
    String[] strs();
    int show1();
    String show2();
}
@MyAnno(per = Person.p1,anno2 = @MyAnno2,strs = {"abc", "bbb"},show1 = 1,show2 = "abc")
public class Worker {
}

元注解:用于描述注解的注解
(1)@Target:描述注解能夠作用的位置
ElementType取值:TYPE可以作用于類上;METHOD:可以作用于方法上懈息;FIELD:可以作用于成員變量上

@Target(value={ElementType.TYPE,})//表示該MyAnno2注解只能作用于類上

(2)@Retention:描述注解被保留的階段
@Retention(RetentionPolicy.RUNTIME):當(dāng)前被描述的注解肾档,會保留到class字節(jié)碼文件中,并被JVM讀取到。
(3)@Documented:描述注解是否被抽取到API文檔中
(4)@Inherited:描述注解是否被子類繼承

在程序使用(解析)注解:獲取注解中定義的屬性值
(1)獲取注解定義位置的對象(Class怒见,Method俗慈,F(xiàn)Ield)
(2)獲取指定的注解:getAnnotation(Class)
(3)調(diào)用注解中的抽象方法獲取配置的屬性值

/**
 * 描述需要執(zhí)行的類名和方法名
 */
@Target({ElementType.TYPE})//可以作用在類上
@Retention(RetentionPolicy.RUNTIME)//希望被保留在RUNTIME階段
public @interface Pro {
    String className();
    String methodName();
}
/**
 * 框架類:前提:不能改變該類的任何代碼,可以創(chuàng)建任意類的對象遣耍,可以執(zhí)行任意方法
 */
@Pro(className = "cn.itcast.day12.demo01.demo06.Demo1",methodName = "show")
public class AnnoTest {
    public static void main(String[] args) throws Exception{
        //1闺阱,解析注解
        //1.1獲取該類的字節(jié)碼文件對象
        Class<AnnoTest> annoTestClass = AnnoTest.class;
        //2,獲取上邊的注解對象
        //其實就是在內(nèi)存中生成了一個該注解接口的子類實現(xiàn)對象
        Pro an = annoTestClass.getAnnotation(Pro.class);
        //3,調(diào)用注解對象中定義的抽象方法,獲取返回值
        String className = an.className();
        String methodName = an.methodName();
        System.out.println(className);
        System.out.println(methodName);

        //3舵变,加載該類進(jìn)內(nèi)存
        Class cls = Class.forName(className);

        //4酣溃,創(chuàng)建對象
        Object obj = cls.newInstance();

        //5,獲取方法對象
        Method method = cls.getMethod(methodName);

        //6,執(zhí)行方法
        method.invoke(obj);
    }
}

案例:
Check.java

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}

Calculator.java

    @Check
    public void add(){
        System.out.println("1+0="+(1+0));
    }

    @Check
    public void sub(){
        System.out.println("1-0="+(1-0));
    }

    @Check
    public void mul(){
        System.out.println("1*0="+(1*0));
    }

    @Check
    public void div(){
        System.out.println("1/0="+(1 / 0));
    }

    public void show(){
        System.out.println("永無bug...");
    }
}

TestCheck.java

/**
 * 簡單的測試框架
 * 當(dāng)祝方法執(zhí)行后,會自動自行被檢測的所有方法(加了Check注解的方法)纪隙,判斷方法是否有異常赊豌,記錄到文件中
 */
public class TestCheck {
    public static void main(String[] args) throws IOException {
        //1,創(chuàng)建計算器對象
        Calculator c = new Calculator();
        //2绵咱,獲取字節(jié)碼文件對象
        Class cls = c.getClass();
        //3碘饼,獲取所有的方法
        Method[] methods = cls.getMethods();

        int num = 0;//出現(xiàn)異常的對象
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));

        for(Method method : methods) {
            //4,判斷方法上是否有Check注解艾恼,有即執(zhí)行
            if (method.isAnnotationPresent(Check.class)) {
                try {
                    method.invoke(c);
                } catch (Exception e) {
                    //5钠绍,捕獲異常
                    //記錄到文件中
                    num++;
                    bw.write(method.getName() + "方法出異常了");
                    bw.newLine();
                    bw.write("異常的名稱:" + e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("異常的原因:" + e.getCause().getMessage());
                    bw.newLine();
                    bw.write("======");
                }
            }
        }
        bw.write("本次測試一共出現(xiàn)"+ num +"次異常");
        bw.flush();
        bw.close();

    }
}

執(zhí)行結(jié)果bug.txt

div方法除異常了
異常的名稱:ArithmeticException
異常的原因:/ by zero
======本次測試一共出現(xiàn)1次異常

小結(jié):
(1)以后大多數(shù)時候五慈,我們會使用注解泻拦,而不是自定義注解忽媒。
(2)注解給誰用?編譯器架曹,解析程序
(3)注解不是程序的一部分闹瞧,可以理解為注解就是一個標(biāo)簽奥邮。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末罗珍,一起剝皮案震驚了整個濱河市覆旱,隨后出現(xiàn)的幾起案子核无,更是在濱河造成了極大的恐慌,老刑警劉巖噪沙,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件曲聂,死亡現(xiàn)場離奇詭異,居然都是意外死亡齐疙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來轿塔,“玉大人勾缭,你說我怎么就攤上這事×┯桑” “怎么了幻梯?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵咬摇,是天一觀的道長。 經(jīng)常有香客問我肛鹏,道長,這世上最難降的妖魔是什么昭雌? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任烛卧,我火速辦了婚禮妓局,結(jié)果婚禮上好爬,老公的妹妹穿的比我還像新娘。我一直安慰自己炬搭,他們只是感情好宫盔,可當(dāng)我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布灼芭。 她就那樣靜靜地躺著般又,像睡著了一般。 火紅的嫁衣襯著肌膚如雪寄悯。 梳的紋絲不亂的頭發(fā)上热某,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天胳螟,我揣著相機與錄音,去河邊找鬼秘遏。 笑死嘉竟,一個胖子當(dāng)著我的面吹牛洋侨,可吹牛的內(nèi)容都是我干的希坚。 我是一名探鬼主播裁僧,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼聊疲,長吁一口氣:“原來是場噩夢啊……” “哼沪悲!你這毒婦竟也來了殿如?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤飞崖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后胯努,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逢防,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡灰署,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年溉箕,在試婚紗的時候發(fā)現(xiàn)自己被綠了肴茄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片但指。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖连躏,靈堂內(nèi)的尸體忽然破棺而出贞滨,到底是詐尸還是另有隱情疲迂,我是刑警寧澤才顿,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站尾组,受9級特大地震影響示弓,放射性物質(zhì)發(fā)生泄漏奏属。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一勇婴、第九天 我趴在偏房一處隱蔽的房頂上張望嘱腥。 院中可真熱鬧,春花似錦橱脸、人聲如沸分苇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽组砚。三九已至吻商,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間糟红,已是汗流浹背艾帐。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工蛉签, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嘴脾,地道東北人。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像泉沾,于是被迫代替她去往敵國和親洲拇。 傳聞我的和親對象是個殘疾皇子棉饶,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容