Java基礎(chǔ)加強——Junit、反射、注解

今日內(nèi)容

1. Junit單元測試
2. 反射
3. 注解

Junit單元測試:

* 測試分類:
    1. 黑盒測試:不需要寫代碼,給輸入值,看程序是否能夠輸出期望的值。
    2. 白盒測試:需要寫代碼的。關(guān)注程序具體的執(zhí)行流程。

* Junit使用:白盒測試
    * 步驟:
        1. 定義一個測試類(測試用例)
            * 建議:
                * 測試類名:被測試的類名Test       CalculatorTest
                * 包名:xxx.xxx.xx.test        cn.itcast.test

        2. 定義測試方法:可以獨立運行
            * 建議:
                * 方法名:test測試的方法名        testAdd()  
                * 返回值:void
                * 參數(shù)列表:空參

        3. 給方法加@Test
        4. 導(dǎo)入junit依賴環(huán)境

    * 判定結(jié)果:
        * 紅色:失敗
        * 綠色:成功
        * 一般我們會使用斷言操作來處理結(jié)果
            * Assert.assertEquals(期望的結(jié)果,運算的結(jié)果);

    * 補充:
        * @Before:
            * 修飾的方法會在測試方法之前被自動執(zhí)行
        * @After:
            * 修飾的方法會在測試方法執(zhí)行之后自動被執(zhí)行
/**
 * 計算器類
 *
 *  測試分類:
 *  1. 黑盒測試:不需要寫代碼,給輸入值,看程序是否能夠輸出期望的值。
 *  2. 白盒測試:需要寫代碼的。關(guān)注程序具體的執(zhí)行流程。更有技術(shù)含量
 *
 *  單元測試的使用步驟:
 *  * Junit使用:白盒測試
 *  * 步驟:
 *      1. 定義一個測試類(測試用例)
 *          * 建議:
 *              * 測試類名:被測試的類名Test       CalculatorTest
 *              * 包名:xxx.xxx.xx.test        cn.itcast.test
 *
 *      2. 定義測試方法:可以獨立運行
 *          * 建議:
 *              * 方法名:test測試的方法名        testAdd()
 *              * 返回值:void
 *              * 參數(shù)列表:空參
 *
 *      3. 給方法加@Test
 *      4. 導(dǎo)入junit依賴環(huán)境
 *
 *  * 判定結(jié)果:
 *      * 紅色:失敗
 *      * 綠色:成功
 *      * 一般我們會使用斷言操作來處理結(jié)果
 *          * Assert.assertEquals(期望的結(jié)果,運算的結(jié)果);
 *
 *  * 補充:(注意哪怕是程序出了錯誤,before和after都也會執(zhí)行,而且執(zhí)行順序好像沒有規(guī)律)
 *      * @Before:
 *          * 修飾的方法會在測試方法之前被自動執(zhí)行
 *      * @After:
 *          * 修飾的方法會在測試方法執(zhí)行之后自動被執(zhí)行
 *
 */
public class CalculatorTest {

    @Before
    public void  init(){
        System.out.println("init....");
    }

    @After
    public void close0(){
        System.out.println("close0...");
    }
    @After
    public void close1(){
        System.out.println("close1...");
    }
    @After
    public void close2(){
        System.out.println("close2...");
    }

    @Test
    public void testAdd(){
        Calculator calculator = new Calculator();
        int result = calculator.add(1, 2);
        System.out.println(result);
    }

    @Test
    public void testSub(){
        Calculator calculator = new Calculator();
        int result = calculator.sub(3, 1);
        //System.out.println(result);
        Assert.assertEquals(2,result);
    }

}

反射:框架設(shè)計的靈魂

* 框架:半成品軟件??梢栽诳蚣艿幕A(chǔ)上進行軟件開發(fā),簡化編碼
* 反射:將類的各個組成部分封裝為其他對象,這就是反射機制
    * 好處:
        1. 可以在程序運行過程中,操作這些對象。
        2. 可以解耦,提高程序的可擴展性。
* 獲取Class對象的方式:
    1. Class.forName("全類名"):將字節(jié)碼文件加載進內(nèi)存,返回Class對象
        * 多用于配置文件,將類名定義在配置文件中。讀取文件,加載類
    2. 類名.class:通過類名的屬性class獲取
        * 多用于參數(shù)的傳遞
    3. 對象.getClass():getClass()方法在Object類中定義著。
        * 多用于對象的獲取字節(jié)碼的方式

    * 結(jié)論:
        同一個字節(jié)碼文件(*.class)在一次程序運行過程中,只會被加載一次,不論通過哪一種方式獲取的Class對象都是同一個。
* Class對象功能:
    * 獲取功能:
        1. 獲取成員變量們
            * Field[] getFields() :獲取所有public修飾的成員變量
            * Field getField(String name)   獲取指定名稱的 public修飾的成員變量

            * Field[] getDeclaredFields()  獲取所有的成員變量,不考慮修飾符
            * Field getDeclaredField(String name)  
        2. 獲取構(gòu)造方法們
            * Constructor<?>[] getConstructors()  
            * Constructor<T> getConstructor(類<?>... parameterTypes)  

            * Constructor<T> getDeclaredConstructor(類<?>... parameterTypes)  
            * Constructor<?>[] getDeclaredConstructors()  
        3. 獲取成員方法們:
            * Method[] getMethods()  
            * Method getMethod(String name, 類<?>... parameterTypes)  

            * Method[] getDeclaredMethods()  
            * Method getDeclaredMethod(String name, 類<?>... parameterTypes)  

        4. 獲取全類名    
            * String getName()  
* Field:成員變量
    * 操作:
        1. 設(shè)置值
            * void set(Object obj, Object value)  
        2. 獲取值
            * get(Object obj) 

        3. 忽略訪問權(quán)限修飾符的安全檢查
            * setAccessible(true):暴力反射
* Constructor:構(gòu)造方法
    * 創(chuàng)建對象:
        * T newInstance(Object... initargs)  

        * 如果使用空參數(shù)構(gòu)造方法創(chuàng)建對象,操作可以簡化:Class對象的newInstance方法
* Method:方法對象
    * 執(zhí)行方法:
        * Object invoke(Object obj, Object... args)  

    * 獲取方法名稱:
        * String getName:獲取方法名
* 案例:
    * 需求:寫一個"框架",不能改變該類的任何代碼的前提下,可以幫我們創(chuàng)建任意類的對象,并且執(zhí)行其中任意方法
        * 實現(xiàn):
            1. 配置文件
            2. 反射
        * 步驟:
            1. 將需要創(chuàng)建的對象的全類名和需要執(zhí)行的方法定義在配置文件中
            2. 在程序中加載讀取配置文件
            3. 使用反射技術(shù)來加載類文件進內(nèi)存
            4. 創(chuàng)建對象
            5. 執(zhí)行方法
/**
 * 反射的基本使用:
 * 反射:將類的各個組成部分封裝為其他對象,這就是反射機制
 * Java代碼在計算機中經(jīng)歷的三個階段
 * 1. Source源碼階段(.java-->.class字節(jié)碼)
 * 2. Class類對象階段(類加載器加載到內(nèi)存)
 * 3. Runtime運行時階段 (創(chuàng)建對象)
 *
 * 獲取Class對象的3種方式
 *  1. Class.forName("全類名"):將字節(jié)碼文件加載進內(nèi)存,返回Class對象
 *      * 多用于配置文件,將類名定義在配置文件中。讀取文件,加載類
 *  2. 類名.class:通過類名的屬性class獲取
 *      * 多用于參數(shù)的傳遞
 *  3. 對象.getClass():getClass()方法在Object類中定義著。
 *      * 多用于對象的獲取字節(jié)碼的方式
 *
 *  注意:同一個字節(jié)碼文件(*.class)在一次程序運行過程中,只會被加載一次,不論通過哪一種方式獲取的Class對象都是同一個。
 *
 */
public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 獲取Class對象的3種方式
        //1.Class.forName("");
        Class clz1 = Class.forName("com.ivyzh.reflect.domain.Person");
        System.out.println(clz1);

        //2.類名.class
        Class clz2 = Person.class;
        System.out.println(clz2);

        //3. 對象.getClass()
        Person person = new Person();
        Class clz3 = person.getClass();
        System.out.println(clz3);

        System.out.println(clz1 ==clz2);
        System.out.println(clz1 ==clz3);

        /**
         * 控制臺輸出結(jié)果:
             class com.ivyzh.reflect.domain.Person
             class com.ivyzh.reflect.domain.Person
             class com.ivyzh.reflect.domain.Person
             true
             true

         */
    }
}


/**
 * 反射的功能使用:
 *  1. 獲取成員變量們
 *      * Field[] getFields() :獲取所有public修飾的成員變量
 *      * Field getField(String name)   獲取指定名稱的 public修飾的成員變量
 *
 *      * Field[] getDeclaredFields()  獲取所有的成員變量,不考慮修飾符
 *      * Field getDeclaredField(String name)
 *  2. 獲取構(gòu)造方法們
 *      * Constructor<?>[] getConstructors()
 *      * Constructor<T> getConstructor(類<?>... parameterTypes)
 *
 *      * Constructor<T> getDeclaredConstructor(類<?>... parameterTypes)
 *      * Constructor<?>[] getDeclaredConstructors()
 *  3. 獲取成員方法們:
 *      * Method[] getMethods()
 *      * Method getMethod(String name, 類<?>... parameterTypes)
 *
 *      * Method[] getDeclaredMethods()
 *      * Method getDeclaredMethod(String name, 類<?>... parameterTypes)
 *
 *  4. 獲取全類名
 *      * String getName()
 */
public class ReflectDemo2 {
    public static void main(String[] args) throws Exception {
        // 獲取Class對象的3種方式
        //1.Class.forName("");
        Class clzPerson = Class.forName("com.ivyzh.reflect.domain.Person2");
        System.out.println(clzPerson);

        // 1. 獲取成員變量們
        Field[] fields = clzPerson.getFields();//獲取所有public修飾的成員變量
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            System.out.println("field-->"+field);
        }
        Field fielda1 = clzPerson.getField("a1");//獲取指定名稱的 public修飾的成員變量
        System.out.println("fielda1-->"+fielda1);
        System.out.println("---------------------------");
        Field[] declaredFields = clzPerson.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            Field declaredField = declaredFields[i];
            System.out.println("declaredField-->"+declaredField);
        }
        Field declaredFieldd = clzPerson.getDeclaredField("d");
        System.out.println("declaredFieldd-->"+declaredFieldd);
        System.out.println("---------------------------");
        // 1.1 設(shè)置成員變量們
        Person2 person = new Person2();
        Field fieldaa = clzPerson.getField("a");
        fieldaa.set(person,10);
        Field fieldName = clzPerson.getDeclaredField("name");
        fieldName.setAccessible(true);//暴力反射,忽略訪問權(quán)限修飾符的安全檢查
        fieldName.set(person,"zhangsan");
        System.out.println("person:"+person);
        // 1.2 獲取成員們的值
        Object nameValue = fieldName.get(person);
        System.out.println("nameValue:"+nameValue);
        System.out.println("---------------------------");

        // 2. 獲取Constructor
        Constructor[] constructors = clzPerson.getConstructors();
        for (int i = 0; i < constructors.length; i++) {
            Constructor constructor = constructors[i];
            System.out.println("constructor-->"+constructor);
        }
        Constructor[] declaredConstructors = clzPerson.getDeclaredConstructors();
        for (int i = 0; i < declaredConstructors.length; i++) {
            Constructor declaredConstructor = declaredConstructors[i];
            System.out.println("declaredConstructor-->"+declaredConstructor);
        }
        System.out.println("---------------------------");
        // 使用構(gòu)造器創(chuàng)建對象
        Constructor constructor = clzPerson.getConstructor();//無參數(shù)構(gòu)造器
        Object p1 = constructor.newInstance();
        System.out.println("p1:"+p1);
        //Constructor declaredConstructor = clzPerson.getDeclaredConstructor(String.class,int.class);
        Constructor declaredConstructor = clzPerson.getDeclaredConstructor( int.class);
        declaredConstructor.setAccessible(true);
        //Object p2 = declaredConstructor.newInstance("lisi",20);
        Object p2 = declaredConstructor.newInstance( 20);
        System.out.println("p2:"+p2);
        System.out.println("---------------------------");

        // 3. 獲取Method

        Method[] methods = clzPerson.getMethods();

        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            System.out.println("method-->"+method);//父類的方法也會被獲取
        }
        Method[] declaredMethods = clzPerson.getDeclaredMethods();
        for (int i = 0; i < declaredMethods.length; i++) {
            Method declaredMethod = declaredMethods[i];
            System.out.println("declaredMethod-->"+declaredMethod);//父類的方法不會被獲取
        }

        Method setName = clzPerson.getDeclaredMethod("setName", String.class);
        Person2 person2 = new Person2();
        setName.setAccessible(true);
        setName.invoke(person2,"wangwu");
        System.out.println("person2:"+person2);
    }
}

/**
 * 反射案例:
 * 需求:寫一個"框架",不能改變該類的任何代碼的前提下,可以幫我們創(chuàng)建任意類的對象,并且執(zhí)行其中任意方法
 *      * 實現(xiàn):
 *          1. 配置文件
 *          2. 反射
 *      * 步驟:
 *          1. 將需要創(chuàng)建的對象的全類名和需要執(zhí)行的方法定義在配置文件中
 *          2. 在程序中加載讀取配置文件
 *          3. 使用反射技術(shù)來加載類文件進內(nèi)存
 *          4. 創(chuàng)建對象
 *          5. 執(zhí)行方法
 */
public class ReflectDemo3 {
    public static void main(String[] args) throws Exception {

        Properties properties = new Properties();
        ClassLoader classLoader = ReflectDemo3.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        properties.load(is);
        String className = properties.getProperty("className");
        String methodName = properties.getProperty("methodName");
        Class<?> clz = Class.forName(className);
        Object instance = clz.newInstance();
        Method declaredMethod = clz.getDeclaredMethod(methodName);
        declaredMethod.setAccessible(true);
        declaredMethod.invoke(instance);

    }
}

pro.properties文件

className=com.ivyzh.reflect.domain.BenzCar
methodName=fix

注解:

* 概念:說明程序的。給計算機看的
* 注釋:用文字描述程序的。給程序員看的

* 定義:注解(Annotation),也叫元數(shù)據(jù)。一種代碼級別的說明。它是JDK1.5及以后版本引入的一個特性,與類、接口、枚舉是在同一個層次。它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等的前面,用來對這些元素進行說明,注釋。
* 概念描述:
    * JDK1.5之后的新特性
    * 說明程序的
    * 使用注解:@注解名稱

?

* 作用分類:
    ①編寫文檔:通過代碼里標(biāo)識的注解生成文檔【生成文檔doc文檔】
    ②代碼分析:通過代碼里標(biāo)識的注解對代碼進行分析【使用反射】
    ③編譯檢查:通過代碼里標(biāo)識的注解讓編譯器能夠?qū)崿F(xiàn)基本的編譯檢查【Override】
* JDK中預(yù)定義的一些注解
    * @Override :檢測被該注解標(biāo)注的方法是否是繼承自父類(接口)的
    * @Deprecated:該注解標(biāo)注的內(nèi)容,表示已過時
    * @SuppressWarnings:壓制警告
        * 一般傳遞參數(shù)all  @SuppressWarnings("all")

* 自定義注解
    * 格式:
        元注解
        public @interface 注解名稱{
            屬性列表;
        }

    * 本質(zhì):注解本質(zhì)上就是一個接口,該接口默認繼承Annotation接口
        * public interface MyAnno extends java.lang.annotation.Annotation {}

    * 屬性:接口中的抽象方法
        * 要求:
            1. 屬性的返回值類型有下列取值
                * 基本數(shù)據(jù)類型
                * String
                * 枚舉
                * 注解
                * 以上類型的數(shù)組

            2. 定義了屬性,在使用時需要給屬性賦值
                1. 如果定義屬性時,使用default關(guān)鍵字給屬性默認初始化值,則使用注解時,可以不進行屬性的賦值。
                2. 如果只有一個屬性需要賦值,并且屬性的名稱是value,則value可以省略,直接定義值即可。
                3. 數(shù)組賦值時,值使用{}包裹。如果數(shù)組中只有一個值,則{}可以省略
    
    * 元注解:用于描述注解的注解
        * @Target:描述注解能夠作用的位置
            * ElementType取值:
                * TYPE:可以作用于類上
                * METHOD:可以作用于方法上
                * FIELD:可以作用于成員變量上
        * @Retention:描述注解被保留的階段
            * @Retention(RetentionPolicy.RUNTIME):當(dāng)前被描述的注解,會保留到class字節(jié)碼文件中,并被JVM讀取到
        * @Documented:描述注解是否被抽取到api文檔中
        * @Inherited:描述注解是否被子類繼承
* 在程序使用(解析)注解:獲取注解中定義的屬性值
    1. 獲取注解定義的位置的對象  (Class,Method,Field)
    2. 獲取指定的注解
        * getAnnotation(Class)
        //其實就是在內(nèi)存中生成了一個該注解接口的子類實現(xiàn)對象

                public class ProImpl implements Pro{
                    public String className(){
                        return "cn.itcast.annotation.Demo1";
                    }
                    public String methodName(){
                        return "show";
                    }
                }
    3. 調(diào)用注解中的抽象方法獲取配置的屬性值
* 案例:簡單的測試框架
* 小結(jié):
    1. 以后大多數(shù)時候,我們會使用注解,而不是自定義注解
    2. 注解給誰用?
        1. 編譯器
        2. 給解析程序用
    3. 注解不是程序的一部分,可以理解為注解就是一個標(biāo)簽
/**
 * * 概念:說明程序的。給計算機看的
 * * 注釋:用文字描述程序的。給程序員看的
 *
 * * 定義:注解(Annotation),也叫元數(shù)據(jù)。一種代碼級別的說明。它是JDK1.5及以后版本引入的一個特性,與類、接口、枚舉是在同一個層次。
 *   它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等的前面,用來對這些元素進行說明,注釋。
 * * 概念描述:
 *  * JDK1.5之后的新特性
 *  * 說明程序的
 *  * 使用注解:@注解名稱
 *
 * * 作用分類:
 *  ①編寫文檔:通過代碼里標(biāo)識的注解生成文檔【生成文檔doc文檔】
 *  ②代碼分析:通過代碼里標(biāo)識的注解對代碼進行分析【使用反射】
 *  ③編譯檢查:通過代碼里標(biāo)識的注解讓編譯器能夠?qū)崿F(xiàn)基本的編譯檢查【Override】
 *  * 注解的定義
 * * JDK中預(yù)定義的一些注解
 * * 自定義注解
 * * 在程序使用(解析)注解:獲取注解中定義的屬性值
 *
 *
 * * JDK中預(yù)定義的一些注解
 *  * @Override :檢測被該注解標(biāo)注的方法是否是繼承自父類(接口)的
 *  * @Deprecated:該注解標(biāo)注的內(nèi)容,表示已過時
 *  * @SuppressWarnings:壓制警告
 *      * 一般傳遞參數(shù)all  @SuppressWarnings("all")
 */
public @interface AnnoDemo1 {

    //1. 屬性的返回值類型有
    int show1();// 基本數(shù)據(jù)類
    String show2();//String
    MyAnno show3();//注解
    MyEnum show6();//枚舉
    int[]  show4();//以上類型的數(shù)組
    MyAnno[] show5();//以上類型的數(shù)組

    //2. 定義了屬性,在使用時需要給屬性賦值

    String name() default "zhangsan";// 如果定義屬性時,使用default關(guān)鍵字給屬性默認初始化值,則使用注解時,可以不進行屬性的賦值

}

/**
 ** 元注解:用于描述注解的注解
 *  * @Target:描述注解能夠作用的位置
 *      * ElementType取值:
 *          * TYPE:可以作用于類上
 *          * METHOD:可以作用于方法上
 *          * FIELD:可以作用于成員變量上
 *  * @Retention:描述注解被保留的階段
 *      * @Retention(RetentionPolicy.RUNTIME):當(dāng)前被描述的注解,會保留到class字節(jié)碼文件中,并被JVM讀取到
 *      * @Retention(RetentionPolicy.CLASS):當(dāng)前被描述的注解,會保留到class字節(jié)碼文件中,但不會被JVM讀取到
 *      * @Retention(RetentionPolicy.SOURCE):當(dāng)前被描述的注解,不會保留到class字節(jié)碼文件中,但不會被JVM讀取到
 * (三個階段:source、class、runtime)
 *  * @Documented:描述注解是否被抽取到api文檔中
 *  * @Inherited:描述注解是否被子類繼承

 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnoDemo3 {
  int value();
}
/**
 * * 概念:說明程序的。給計算機看的
 * * 注釋:用文字描述程序的。給程序員看的
 *
 * * 定義:注解(Annotation),也叫元數(shù)據(jù)。一種代碼級別的說明。它是JDK1.5及以后版本引入的一個特性,與類、接口、枚舉是在同一個層次。
 *   它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等的前面,用來對這些元素進行說明,注釋。
 * * 概念描述:
 *  * JDK1.5之后的新特性
 *  * 說明程序的
 *  * 使用注解:@注解名稱
 *
 * * 作用分類:
 *  ①編寫文檔:通過代碼里標(biāo)識的注解生成文檔【生成文檔doc文檔】
 *  ②代碼分析:通過代碼里標(biāo)識的注解對代碼進行分析【使用反射】
 *  ③編譯檢查:通過代碼里標(biāo)識的注解讓編譯器能夠?qū)崿F(xiàn)基本的編譯檢查【Override】
 *  * 注解的定義
 * * JDK中預(yù)定義的一些注解
 * * 自定義注解
 * * 在程序使用(解析)注解:獲取注解中定義的屬性值
 *
 *
 * * JDK中預(yù)定義的一些注解
 *  * @Override :檢測被該注解標(biāo)注的方法是否是繼承自父類(接口)的
 *  * @Deprecated:該注解標(biāo)注的內(nèi)容,表示已過時
 *  * @SuppressWarnings:壓制警告
 *      * 一般傳遞參數(shù)all  @SuppressWarnings("all")
 */
public @interface MyAnno {


}
/**
 * 獲取指定的注解
 *      * getAnnotation(Class)
 */
@Pro(className = "com.ivyzh.reflect.domain.BMWCar",methodName = "run")
public class ReflectTest {
    public static void main(String[] args) throws  Exception {

        Pro annotation = ReflectTest.class.getAnnotation(Pro.class);
        String className = annotation.className();
        String methodName = annotation.methodName();
        System.out.println(className);
        System.out.println(methodName);

        Class<?> clz = Class.forName(className);
        Object car = clz.newInstance();
        Method declaredMethod = clz.getDeclaredMethod(methodName);
        declaredMethod.setAccessible(true);
        declaredMethod.invoke(car);
    }
}

Calulator

/**
 * 計算器類
 */
public class Calculator {
    @Check(a=5,b=3)
    public int add(int a,int b){
        return a+b;
    }
    @Check
    public int sub(int a,int b){
        return a+b;
    }
    @Check
    public int mul(int a,int b){
        return a*b;
    }
    @Check(a=10,b=0)
    public int div(int a,int b){
        return a/b;
    }

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

CalulatorTest

/**
 * 案例:簡單的測試框架
 * 1.
 * 2.
 */

public class CaculatorTest {
    public static void main(String[] args) throws  Exception {

        Calculator calculator = new Calculator();
        Method[] declaredMethods = calculator.getClass().getDeclaredMethods();

        int bugNum = 0;
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("bug.txt"));


        for (int i = 0; i < declaredMethods.length; i++) {
            Method declaredMethod = declaredMethods[i];
            if(declaredMethod.isAnnotationPresent(Check.class)){
                Check annotation = declaredMethod.getAnnotation(Check.class);
                int a = annotation.a();
                int b = annotation.b();
                try {
                    Object result =  declaredMethod.invoke(calculator,a,b);
                    System.out.println(a+" "+declaredMethod.getName()+" "+b+" result:"+result);
                }catch (Exception e){
                    e.printStackTrace();
                    bugNum++;
                    bufferedWriter.write(declaredMethod.getName()+" 出現(xiàn)異常了");
                    bufferedWriter.newLine();
                    bufferedWriter.write("異常名稱:"+e.getCause().getClass().getSimpleName());
                    bufferedWriter.newLine();
                    bufferedWriter.write("異常原因:"+e.getCause().getMessage());
                    bufferedWriter.newLine();
                    bufferedWriter.write("----------------------");
                    bufferedWriter.newLine();
                }

            }

        }

        bufferedWriter.write("本次運行一共出現(xiàn) "+bugNum+" 次異常");
        bufferedWriter.flush();
        bufferedWriter.close();

    }
}

Check

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
    int a() default 5;
    int b() default 3;
}

END.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 看到這邊解釋注解的博客非常好。放一下原版鏈接。進行了一些簡化。 Annotation 中文譯過來就是注解、標(biāo)釋的意...
    春天的蜜蜂閱讀 1,186評論 0 0
  • 轉(zhuǎn)自https://blog.csdn.net/briblue/article/details/73824058#...
    扎Zn了老Fe閱讀 1,153評論 0 4
  • 適應(yīng)孤獨,學(xué)會愛自己! 2017年7月22日 星期六 外面下著雨 廣州 大學(xué)四年很快很快就過...
    HU托克拉克閱讀 333評論 0 3
  • 自定義 Model 網(wǎng)址 方案一:網(wǎng)址ID+數(shù)字 在model中定義 to_param 函數(shù) 方案二: 亂數(shù) ID...
    bigbug_閱讀 474評論 0 0
  • 文/輝皇 20160210 我一句,你一句,心心相印情飄絮。夜半難相聚。 愁千言,恨千言,深深牽掛難相見。徒...
    梅蘭竹菊668閱讀 322評論 0 2

友情鏈接更多精彩內(nèi)容