Junit单元测试、反射、注解

一、Junit单元测试

    1、单元测试:可以代替掉程序中的main方法。程序可以从单元测试方法开始执行。

    使用:

        1. 要在单元测试方法上面加上注解 @Test

        2. 以单元测试的方式去运行即可。

    要求:

        1. 单元测试方法的方法名一般以test开头 (软性规定)

        2. 单元测试方法要以public 修饰,没有返回值,没有参数 (硬性规定)

    单元测试方法的运行:

        1. 如果选中某个单元测试方法,然后右键运行,那么运行的就是这个方法。

        2. 如果选中的是某个人,然后右键运行,那么运行的就是这个类中所有的单元测试方法。

public class Demo01Test {

    @Test

    public void testMethod() {

        System.out.println("testMethod...");

    }

 

    @Test

    public void testFunction() {

        System.out.println("testFunction");

    }

}

2、单元中其他注解

   在单元测试中,还有一些其他注解,可以完成一些功能

    @Before:加上此注解的方法,会在每次单元测试方法执行之前执行。

    @After: 加上此注解的方法,会在每次单元测试方法执行之后执行。

    @BeforeClass: 加上此注解的方法,会在所有单元测试方法执行前执行,终身只执行一次。

    @AfterClass: 加上此注解的方法,会在所有单元测试方法执行后执行,终身只执行一次。

    注意:

        BeforeClass和AfterClass 这两个注解修饰的方法必须是静态方法

public class Demo02Test {

 

    @AfterClass

    public static void afterClassMethod() {

        System.out.println("afterClassMethod....");

    }

 

 

    @BeforeClass

    public static void beforeClassMethod() {

        System.out.println("beforeClassMethod...");

    }

 

 

    @Before

    public void beforeMethod() {

        System.out.println("beforeMethod...");

    }

 

    @After

    public void afterMethod() {

        System.out.println("afterMethod...");

    }

 

 

    @Test

    public void testMethod() {

        System.out.println("testMethod...");

    }

 

    @Test

    public void testFunction() {

        System.out.println("testFunction...");

    }

}

二、反射

    1、类的Class对象的三种获取方式

    1. 通过对象名.getClass方法获取

        Class getClass(): 获取此对象所在类的Class类型的对象.

    2. 通过类名.class属性获取

        每一个数据类型,都有一个属性,叫做class,这个使用这个属性就可以获取对应的class

    3. 通过Class类的静态方法forName进行获取

        static Class forName(String className): 参数传递字符串类型的全类名(包含包的类名, 包名.类名)

 

    推荐第三种: 因为第三种更加灵活.

 

    注意:

 

        每一个类的Class类型的对象只有一个,所以不管怎么获取,获取到的都是同一个Class对象。

public class Demo01Reflect {

    public static void main(String[] args) throws ClassNotFoundException {

        //1. 通过对象名.getClass方法获取

        Person p = new Person();

        Class clazz1 = p.getClass();

        System.out.println(clazz1);

 

        //2. 通过类名.class属性获取

        Class clazz2 = Person.class;

        System.out.println(clazz2);

 

        //3. 通过Class类的静态方法forName进行获取

        Class clazz3 = Class.forName("cn.itcast.demo02.Person");

        System.out.println(clazz3);

 

        System.out.println(clazz1 == clazz2);

        System.out.println(clazz1 == clazz3);

    }

}

2、Class对象中的常用方法:

        String getSimpleName(): 获取简单类名. (不包含包的类名)

        String getName():获取全类名 (包含包的类名)

        T newInstance():直接创建该类的对象。

public class Demo02Reflect {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {

        //获取Person类的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //调用getSimpleName,获取类名

        System.out.println(clazz.getSimpleName()); //Person

        //调用getName, 获取全类名

        System.out.println(clazz.getName()); //cn.itcast.demo02.Person

 

        //T newInstance():直接创建该类的对象。

        //clazz是Person类的Class对象,所以调用newInstance创建的是Person对象.

        Object obj = clazz.newInstance();

        Person p = (Person)obj;

        p.setName("大幂幂");

        p.setAge(12);

        System.out.println(p.getName() + "-" + p.getAge());

    }

}

 

3、Constructor: 构造方法

    Method:      成员方法

    Filed:       成员变量

    反射获取类的构造方法。

    Class类中,有一些方法,可以获取对应的构造方法:

        Constructor[] getConstructors(): 获取该类中的所有的公共(public)的构造方法。

        Constructor getConstructor(Class... parameterTypes): 获取该类中指定的公共的构造方法。 参数表示要获取的构造方法的参数列表。

    上面两个方法只能获取public修饰的构造方法。

    Constructor表示构造方法, 里面有一些方法可以完成功能。

        T newInstance(Object... initargs): 这个方法可以创建一个对象。

            参数initargs: 可变参,表示调用构造方法的时候传递的实际参数

            返回值: 使用该构造方法创建的对象.

public class Demo03Reflect {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {

        method2();

    }

 

    //获取Person类中的空参数构造方法,然后使用这个空参数构造方法创建一个Person对象

    public static void method2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        //获取Person类的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //调用getConstructor获取指定的构造方法

        //在getConsturctor中,参数表示的含义是要获取的构造方法的参数列表

        //因为要获取的是空参数构造方法,所以在getConstructor方法中不需要传递参数。

        Constructor c = clazz.getConstructor();

        //通过这个构造方法去创建一个对象

        //直接调用构造方法的newInstance方法就可以根据这个构造方法创建一个对象

        //因为是通过空参数构造方法创建度夏宁,所以newInstance方法中不需要写任何的参数。

        Object obj = c.newInstance();

        //打印这个对象

        System.out.println(obj);

    }

 

    //获取Person类中所有的构造方法并打印

    public static void method1() throws ClassNotFoundException {

        //获取Person类的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //调用getConstructors,获取该类的所有的公共的构造方法。

        Constructor[] cs = clazz.getConstructors();

        //遍历这个数组,打印每一个元素

        for (Constructor c : cs) {

            System.out.println(c);

        }

    }

}

4、反射获取有参构造并且使用。

    Class类中,有一些方法,可以获取对应的构造方法:

        Constructor[] getConstructors(): 获取该类中的所有的公共(public)的构造方法。

        Constructor getConstructor(Class... parameterTypes): 获取该类中指定的公共的构造方法。 参数表示要获取的构造方法的参数列表。

    上面两个方法只能获取public修饰的构造方法。

    Constructor表示构造方法, 里面有一些方法可以完成功能。

        T newInstance(Object... initargs): 这个方法可以创建一个对象。

            参数initargs: 可变参,表示调用构造方法的时候传递的实际参数

            返回值: 使用该构造方法创建的对象.

    注意:

        任何类型都有.class。 包括基本类型。

public class Demo04Reflect {

    //反射获取到Person类中的有参构造 Person(String name, int age),然后通过这个构造方法创建Person对象

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        //获取这个类的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //可以通过Class对象获取Person类中的有参构造方法

        //因为要获取的构造方法的第一个参数是String类型,第二个参数是int类型。

        //所以要在这个getConstructor方法的第一个参数位置传递String类型的Class对象。 第二个参数传递int类型的class对象

        Constructor c = clazz.getConstructor(String.class, int.class);

        //根据这个构造方法创建对象

        //因为获取到的构造方法是有参数的构造方法,所以使用这个构造方法创建对象时必须要传递实际参数。

        //构造方法第一个参数是字符串,第二个参数是int类型,所以在newInstance参数位置给出对应的数据。

        Object obj = c.newInstance("大幂幂", 30); //

 

        //打印

        System.out.println(obj);

    }

}

5、暴力反射(不推荐, 因为会破坏封装性)

    Constructor[] getDeclaredConstructors():获取类中的所有的构造方法,包括私有

    Constructor getDeclaredConstructor(Class... parameterTypes): 获取指定的构造方法,包括私有

   在Java中,有一个权限安全检查机制,私有的内容虽然可以获取到,但是并不能直接去使用。

    解决方式: 取消这个权限安全检查机制。

    Constructor: 构造方法

    Method:      成员方法

    Field:       字段(成员变量)

    这是三个类有一个共同的父类,叫做AccessibleObject, 里面有一个方法,可以取消权限检查

        void setAccessible(boolean flag): 如果参数是true,表示取消安全检查

    

public class Demo05Reflect {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {

        method2();

    }

 

    //使用反射获取私有构造方法,并且进行使用.

    //private Person(String name)

    public static void method2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        //获取Person类的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //获取私有的构造方法

        Constructor c = clazz.getDeclaredConstructor(String.class);

 

        //在使用之前取消权限安全检查

        c.setAccessible(true);

 

        //使用这个构造方法创建对象。传递的实际参数为大幂幂

        Object obj = c.newInstance("大幂幂");

        System.out.println(obj);

    }

 

 

    //获取所有的构造方法

    public static void method1() throws ClassNotFoundException {

        //获取Person类的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //获取所有的构造方法

        Constructor[] cs = clazz.getDeclaredConstructors();

        //遍历

        for (Constructor c : cs) {

            System.out.println(c);

        }

    }

}

6、反射获取成员方法并使用。

    在Class类中,有一些方法,可以获取到类的成员方法

        Method getMethod(String name, Class... parameterTypes): 获取指定的成员方法,第一个参数为成员方法的名字。 第二个参数是该成员方法的参数列表。

        Method[] getMethods(): 获取所有的成员方法。

    注意: 上面两个方法,只能获取到public修饰的方法,其他权限获取不到.

    Method这个类表示的是方法。 这个类中有一些方法可以完成一些功能。

        Object invoke(Object obj, Object... args): 让该方法被调用执行。

            参数obj:表示通过哪个对象去调用

            参数args:表示调用该方法时传递的实际参数。

            返回值: 这个方法调用的返回值。

 

public class Demo06Reflect {

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

        method2();

    }

 

    //获取指定的空参数成员方法,然后并调用执行。

    //eat()

    public static void method2() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {

        //获取Person类的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //获取指定的成员方法

        //这个getMethod方法第一个参数为要获取的方法名,第二个参数为获取的方法的参数列表

        //因为eat方法没有参数,所以只需要传递一个方法名即可

        Method method = clazz.getMethod("eat");

 

        Object obj = clazz.newInstance(); //通过反射创建一个Person对象

 

        //让这个eat()方法被调用执行

        //invoke方法要两个参数,第一个参数表示通过哪个对象去调用这个方法,第二个对象是一个可变参数,表示调用这个方法时传递的实际参数

 

        //此方法执行(eat方法), 这个方法是通过obj对象调用的,没有参数

        method.invoke(obj); //相当于 obj.eat();

    }

 

 

    //获取所有的公共的成员方法并使用

    public static void method1() throws ClassNotFoundException {

        //获取Person类的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //调用getMethods,获取到所有的成员方法

        Method[] ms = clazz.getMethods(); //获取到的成员方法包括继承下来的。

        //遍历

        for (Method m : ms) {

            System.out.println(m);

        }

    }

}

7、反射获取有参成员方法并调用

    在Class类中,有一些方法,可以获取到类的成员方法

        Method getMethod(String name, Class... parameterTypes): 获取指定的成员方法,第一个参数为成员方法的名字。 第二个参数是该成员方法的参数列表。

        Method[] getMethods(): 获取所有的成员方法。

    注意: 上面两个方法,只能获取到public修饰的方法,其他权限获取不到.

    Method这个类表示的是方法。 这个类中有一些方法可以完成一些功能。

        Object invoke(Object obj, Object... args): 让该方法被调用执行。

            参数obj:表示通过哪个对象去调用

            参数args:表示调用该方法时传递的实际参数。

            返回值: 这个方法调用的返回值。

 

public class Demo07Reflect {

    //使用反射获取有参成员方法并且使用

    //public void sleep(String address, int time)

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

        //获取这个类的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //获取要调用的成员方法

        Method m = clazz.getMethod("sleep", String.class, int.class);

 

        //因为调用方法需要Person对象,所以获取一个Person对象

        Object obj = clazz.newInstance();

 

        //调用invoke方法,让方法执行。

        //m指的是sleep方法,所以说当通过m调用invoke的时候。sleep方法会执行。

        //因为第一个参数传递的是obj,所以是通过这个obj调用的sleep方法

        //因为后面可变参数传递的是"天上人间", 5, 所以表示这个sleep方法被调用的时候传递的实际参数是这两个

        m.invoke(obj, "天上人间", 5); //obj.sleep("天上人间", 5);

    }

}

8、  反射获取Person中的get/set方法,进行赋值和取值的操作

public class Demo08Reflect {

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

        //获取Perosn的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //获取这个Person类中的setName方法

        Method setMethod = clazz.getMethod("setName", String.class);

        //创建一个对象

        Object obj = clazz.newInstance();

        //通过这个obj对象执行setName方法,给姓名赋值

        setMethod.invoke(obj, "大幂幂");

 

        //获取这个Person类的getName方法

        Method getMethod = clazz.getMethod("getName");

        //通过反射的方式调用getName方法,获取obj对象的姓名属性

        //invoke方法的返回值,就是getName方法调用之后的结果

        Object result = getMethod.invoke(obj); //相当于obj.getName();

 

        System.out.println(result);

    }

}

9、反射获取成员变量

    在Class中有些方法,可以获取成员变量

        Field getField(String name): 获取指定的成员变量,参数为成员变量名字

        Field[] getFields():获取所有的成员变量。

    注意: 上面两个方法,只能获取public修饰的成员变量。

    Field表示的就是成员变量。里面有一些方法,可以去使用

        void set(Object obj, Object value):给这个成员变量赋值

            参数obj:表示给哪个对象的该成员变量赋值

            参数value:表示赋值成什么

        Object get(Object obj):获取成员变量的值

            参数obj:表示获取哪个对象的该成员变量的值。

public class Demo09Reflect {

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

        method2();

    }

 

    //获取指定的成员变量并使用

    public static void method2() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {

        //获取Perosn的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //通过这个Class对象获取到Person中的hobby成员变量

        Field field = clazz.getField("hobby");

        //通过反射创建对象

        Object obj = clazz.newInstance();

        //调用Field的set方法,给obj的该属性赋值

        field.set(obj, "抽烟"); //给obj的hobby属性赋值成了抽烟

 

        //调用get方法获取该对象的hobby属性值

        Object result = field.get(obj); //获取obj对象的hobby,并返回

        System.out.println(result);

 

    }

 

 

    //获取所有的成员变量

    public static void method1() throws ClassNotFoundException {

        //获取Perosn的Class对象

        Class clazz = Class.forName("cn.itcast.demo02.Person");

        //获取所有的成员变量

        Field[] fields = clazz.getFields();

        //遍历

        for (Field field : fields) {

            System.out.println(field);

        }

    }

}

三、注解

 1、注解: @XXX

    1. 注解是JDK1.5之后才有

    2. 注解可以加在类上面,方法上面,变量上面....

    3. 程序可以根据注解完成一些功能

    注解和注释:

        注释: 是给程序员看的, 注释被程序编译和执行。

        注解: 是给程序看的, 程序可以根据注解完成一些功能。

    常见的注解:

        @Override: 验证是否是重写父类的方法。

        @FunctionalInterface: 验证是否是函数式接口。

        @Deprecated: 方法已过时

public class Demo01Anno {

    public static void main(String[] args) {

        method();

    }

    @Deprecated

    public static void method() {

 

    }

}

2、 注解的定义格式:

    public @interface 注解名 {

 

    }

public class Demo02Anno {

 

//    @Student(name = "大幂幂", age = 20, hobbies = {"抽烟", "喝酒", "洗脚"})

    @Student(name = "大幂幂", age = 20, hobbies = "抽烟")

    public void method() {

 

    }

}

 

@Book("红楼梦")

public class Demo03Anno {

 

    @Book("三国演义")

    int num;

 

    //表示把"西游记" 赋值给了Book注解value属性

    @Book("西游记")

    public void method() {

 

    }

}

3、 一个注解中可以有一些属性。

 

    属性的定义格式:

        1. 数据类型 属性名();

        2. 数据类型 属性名() default 默认值;

 

    注意,注解中属性的数据类型必须是以下内容

        1. 可以是所有的基本类型。 byte short int long float double char boolean

        2. 字符串, Class, 枚举, 注解类型。

        3. 以上所有类型的一维数组。

 

    使用注解的注意事项:

        1. 如果注解中的某个属性没有默认值,那么在使用注解的时候,必须要给这个属性赋值。

        2. 如果注解中某个属性有默认值, 在使用注解的时候,可以赋值,也可以不赋值,如果不赋值,那么该属性的值为默认值

        3. 如果注解某个属性是一个数组,那么给该属性赋值的时候,可以使用大括号包裹起来 比如 {"aa", "bb", "cc"}

        4. 如果给数组类型的属性赋值的时候,该数组中只有一个值,那么可以省略大括号。

 

    如果要使用注解,直接在类或者方法或者变量上面加上@注解,如果这个注解有需要被赋值的属性,后面

    跟上小括号,在小括号中给属性赋值即可。

public @interface Student {

    //姓名属性

    String name();

 

    //年龄属性

    int age() default 10;

 

    //爱好

    String[] hobbies();

}

4、如果一个注解中只有一个没有默认值的属性,并且这个属性叫做value, 那么再给这个属性赋值的时候,可以省略属性名。

    反之必须写全

public @interface Book {

    //书名

    String value();

 

    //价格

    int price() default 100;

}

 

四、元注解

 1、元注解。

        元注解是jdk提供的,用来修饰注解的注解(加在注解上面的注解)

    常用的元注解:

        1. Target: 可以限制注解的使用位置

        2. Retention: 可以限制注解的生命周期

@MyAnno

public class Demo01Anno {

 

    @MyAnno

    public void method() {

 

    }

}

 

  在java中还有一个元注解,叫做@Retention,可以限制注解的生命周期

@MyAnno1

@MyAnno2

@MyAnno3

public class Demo02Anno {

}

 

 

2、模拟单元测试。

    自定义一个注解@MyTest。

    然后再一个类中定义一些方法,在其中的方法上加上@MyTest注解,然后获取这个类中的所有方法,并且运行

    带有@MyTest的方法

3、Target是jdk提供的一个元注解,用来修饰注解, 可以限制注解的使用范围。

 

    Target这个元注解中有一个属性叫做value,用来表示被修饰的注解可以使用在哪个位置。这个

    参数是一个ElementType[]。

 

    ElementType是一个枚举,枚举其实就是对象,枚举中的每一个成员变量都是自己的对象。

 

    Target注解的参数要传递ElementType的属性值

 

    枚举中有下面属性,每一个属性都有特别的含义

    ElementType.TYPE: 用在类,接口上

    ElementType.FIELD:用在成员变量上

    ElementType.METHOD: 用在方法上

    ElementType.PARAMETER:用在参数上

    ElementType.CONSTRUCTOR:用在构造方法上

    ElementType.LOCAL_VARIABLE:用在局部变量上

//表示被修饰的注解,既可以使用在方法上,又可以使用在类或者接口的上面

@Target({ElementType.METHOD, ElementType.TYPE})

public @interface MyAnno {

}

 

 

4、 @Retention 是一个元注解,可以限制注解的声明 周期, 如果不使用这个元注解,那么注解默认在

    源代码阶段和编译后的.class阶段有效,一旦程序运行,那么注解就会消失。

    Retention这个元注解中有一个属性叫做value, 所以我们给这个属性赋值的时候可以省略属性名。

    并且这个value表示的含义为被修饰注解的声明周期。 这个value属性是 RetentionPolicy类型

    我们可以给value属性传递三个东西:

        RetentionPolicy.SOURCE: 表示被修饰的注解只在源代码阶段有效。

        RetentionPolicy.CLASS:  表示被修饰的注解在源代码阶段和编译后的.class文件中有效,一旦运行之后就会消失

        RetentionPolicy.RUNTIME:表示被修饰的注解在源代码阶段,编译后的.class并且运行时有效。

//这个注解只在源代码中有效。编译后就会消失

@Retention(RetentionPolicy.SOURCE)

public @interface MyAnno1 {

}

 

//在源代码阶段和编译后的class中有效,运行时期内存中是没有的

@Retention(RetentionPolicy.CLASS)

public @interface MyAnno2 {

}

 

 

//运行时期也有效

@Retention(RetentionPolicy.RUNTIME)

public @interface MyAnno3 {

}

 

5、注解的解析,获取注解中的内容并使用,比如获取注解中的属性。

 

    相关API

        Annotation接口: 是所有注解的根接口。 所有的注解都默认实现了这个接口。

        AnnotatedElement接口: 里面的方法可以对注解进行操作。

            boolean isAnnotationPresent(Class annotationClass):判断是否有指定的注解。 参数Class对象为注解的Class

            T getAnnotation(Class annotationClass): 获取指定的注解。 参数是注解的.class对象。 要获取哪个注解,就传递哪个注解的.class

            Annotation[] getAnnotations():获取所有的注解

 

        解析注解,必须要结合反射技术。

        AnnotatedElement这个接口下面有一些实现类,分别是 Class, Method, Filed。 所以我们可以通过这些实现类对象化

        去调用上面操作注解的方法。

 

        如果通过Class对象调用上面的方法,比如getAnnotations,那么就是获取类上面的注解。

        如果通过Method对象调用上面的方法,获取的就是方法上面的注解

        如果通过Field对象调用上面的注解,获取的就是成员变量上的注解....

 

        想要获取什么上的注解,那么就通过什么对象去调用操作注解的方法就可以了。

 

public class Demo01AnnoParse {

    //获取到BookStore这个类上面的注解属性并且打印

    //解析注解要通过反射技术,如果要获取类上面的注解通过Class对象调用getAnnotation获取注解即可

    public static void main(String[] args) throws ClassNotFoundException {

        //获取BookStore这个类的Class对象

        Class clazz = Class.forName("cn.itcast.demo05.BookStore");

        //判断这个类上面有没有Book注解。

        boolean flag = clazz.isAnnotationPresent(Book.class);

        //如果这个类上面有Book注解,那么就获取

        if (flag) {

            //调用getnnotation获取指定的注解

            Annotation annotation = clazz.getAnnotation(Book.class);

            //获取到的注解真正是Book,可以向下转型成Book,然后获取里面的属性

            Book book = (Book)annotation;

            //打印注解的属性

            System.out.println(book.value());

            System.out.println(book.price());

            System.out.println(book.author());

        }

    }

}

 

6、模拟单元测试。

    自定义一个注解@MyTest。

    然后再一个类中定义一些方法,在其中的方法上加上@MyTest注解,然后获取这个类中的所有方法,并且运行

    带有@MyTest的方法

public class Demo02MyTest {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {

        //获取MyTestClass的Class对象

        Class clazz = Class.forName("cn.itcast.demo05.MyTestClass");

        //创建对象,留作调用方法使用

        Object obj = clazz.newInstance();

        //获取这个类中所有的成员方法

        Method[] methods = clazz.getMethods();

        //遍历这个数组,获取到每一个方法

        for (Method method : methods) {

            //拿到这个方法,判断这个方法上有没有@MyTest注解,如果有,就执行这个方法

            if(method.isAnnotationPresent(MyTest.class)) {

                method.invoke(obj); //通过obj对象调用了这个方法

            }

        }

    }

}

 

 

 

@Book(value = "西游记", price = 100, author = "吴承恩")

public class BookStore {

    public void method() {

 

    }

}

 

 

//使用元注解,让Book在运行时期也有效

@Retention(RetentionPolicy.RUNTIME)

public @interface Book {

    //书名

    String value();

    //价格

    int price();

    //作者

    String author();

}

 

public class MyTestClass {

    @MyTest

    public void method1() {

        System.out.println("method1");

    }

 

    public void method2() {

        System.out.println("method2");

    }

 

    public void method13() {

        System.out.println("method3");

    }

 

    @MyTest

    public void method4() {

        System.out.println("method4");

    }

}

 

@Retention(RetentionPolicy.RUNTIME) //注解在运行时期有效

@Target(ElementType.METHOD) //只能加在方法上

public @interface MyTest {

 

}

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值