0


单元测试&反射&注解

单元测试

     就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。

咱们之前是如何进行单元测试的?有啥问题 ?

Junit单元测试框架

      可以用来对方法进行测试,它是由Junit公司开源出来的 

具体步骤

Junit框架的常见注解

public class StringUtilTest {

    @Test
    @Before
    public void testPrintNumber(){

        StringUtil.printNumber("哈哈");
        StringUtil.printNumber(null);
    }

    @Test
    public void testGetMaxIndex(){

        int sum = new StringUtil().getMaxIndex("蝙蝠侠不打你了");
        System.out.println(sum);

        Assert.assertEquals("警告,警告",6,sum);
    }

    @Test
    @After
    public void testPrint(){

        System.err.println("结束");
    }
}

反射(Reflection)

      反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。 

                                          ![](https://img-blog.csdnimg.cn/9f770fdffa7f4aeeb7f910bad4a4c70a.png)

反射学什么?

获取Class对象的三种方式

1.直接使用类名.class获取:Class c1 = 类名.class

2.调用Class提供的方法:Class c2 = Class.forName("全类名")

3.调用Object提供的方法:Class c3 = 对象.getClass()

public class Demo1 {

    @Test
   public void testDemo01() throws ClassNotFoundException {
       Class catClass = Cat.class;
       System.out.println(catClass.getName());

       Class aClass = Class.forName("com.itheima.b_反射.Cat");
       System.out.println(aClass);

       Class aClass1 = new Cat().getClass();
       System.out.println(aClass1);
   }
}

获取类的构造器

/*
获取构造器[下面是Class的方法]
    Constructor<?>[] getConstructors()    获取所有的公共构造器(只能获取public修饰的)
    Constructor<?>[] getDeclaredConstructors()    获取全部构造器(只要存在就能拿到)
    Constructor<T> getConstructor(Class<?>... parameterTypes)    获取某个公共构造器(只能获取public修饰的)
    Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)    获取某个构造器(只要存在就能拿到)

使用构造器(创建对象)[下面是Constructor的方法]
    T newInstance(Object... initArgs)    调用此构造器对象表示的构造器,并传入参数,完成对象的初始化并返回
    public void  setAccessible(boolean flag)    设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰构造器反射创建对象,需要暴力反射(禁止JVM检查构造方法的访问权限)
*/
public class Demo2 {

    @Test
    public void testConstructor() throws NoSuchMethodException {

        Class<Cat> clazz = Cat.class;

        //获取全部构造器(public)
        Constructor[] constructors = clazz.getConstructors();

        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

        Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }

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

        Constructor<Cat> constructor = clazz.getConstructor();
        System.out.println(constructor);
        System.out.println("===============================");
        Constructor<Cat> declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println("方法名:" + declaredConstructor.getName() + "参数个数:"+ declaredConstructor.getParameterCount());
    }

    @Test
    public void testNew() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        Class calazz = Cat.class;

        Constructor declaredConstructor = calazz.getDeclaredConstructor(String.class, int.class);

        declaredConstructor.setAccessible(true);

        Cat 加菲猫 = (Cat)declaredConstructor.newInstance("加菲猫", 3);

        System.out.println(加菲猫);
    }
}

获取类的成员变量

public class Demo3 {

   @Test
    public void testField() throws NoSuchFieldException {

       Class<Cat> catClass = Cat.class;

       //获取类的所有公共成员变量(只能获取public修饰的)
       Field[] fields = catClass.getFields();
       for (Field field : fields) {
           System.out.println(field);
       }

       System.out.println("===============");
       //获取类的全部成员变量
       Field[] declaredFields = catClass.getDeclaredFields();
       for (Field declaredField : declaredFields) {
           System.out.println(declaredField.getName() + declaredField.getType());
       }
       System.out.println("====================");
       Field a = catClass.getField("a");//获取某个类的成员变量,只要存在就能拿到
       System.out.println(a);

       Field age = catClass.getDeclaredField("age");
       System.out.println(age);
   }

   @Test
   public void test2() throws NoSuchFieldException, IllegalAccessException {

       Class clazz = Cat.class;

       Cat cat = new Cat();
      // System.out.println(cat);

       Field age = clazz.getDeclaredField("age");

       Field name = clazz.getDeclaredField("name");
       //暴力反射
       age.setAccessible(true);
       name.setAccessible(true);

       age.set(cat,5);
       name.set(cat,"哈哈");
       System.out.println(cat);

       //取值
       Object o = age.get(cat);
       System.out.println(o);
   }
}

获取类的成员方法

/*
获取成员方法[Class提供]
    Method[] getMethods()    获取类的全部公共成员方法(只能获取public修饰的)
    Method[] getDeclaredMethods()    获取类的全部成员方法(只要存在就能拿到)
    Method getMethod(String name, Class<?>... parameterTypes)     获取类的某个公共成员方法(只能获取public修饰的)
    Method getDeclaredMethod(String name, Class<?>... parameterTypes)    获取类的某个成员方法(只要存在就能拿到)

使用成员方法(执行方法)[Method提供]
    public Object invoke(Object obj, Object... args)    触发某个对象的该方法执行。
    public void  setAccessible(boolean flag)    设置为true,表示禁止检查访问控制(暴力反射)

注意
    使如果想使用private修饰的成员方法,需要暴力反射
*/
public class Demo4 {

    @Test
    public void testMethods() throws NoSuchMethodException {
        Class<Cat> catClass = Cat.class;

        Method[] methods = catClass.getMethods();
        for (Method method : methods) {
            System.out.println("方法名:"+ method.getName() + "返回值类型:" + method.getReturnType());
        }

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

        Method[] declaredMethods = catClass.getDeclaredMethods();

        for (Method declaredMethod : declaredMethods) {
            System.out.println("方法名:"+ declaredMethod.getName() + "返回值类型" + declaredMethod.getReturnType());
        }

        System.out.println("===========================");
        Method eat = catClass.getDeclaredMethod("eat");
        System.out.println("方法名:"+ eat.getName() + "返回值类型" + eat.getReturnType());

        System.out.println("===========================");
        Method eat1 = catClass.getDeclaredMethod("eat", String.class);
        System.out.println("方法名:"+ eat1.getName() + "返回值类型" + eat1.getReturnType());
    }

    @Test
    public void tese2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        Class<Cat> clazz = Cat.class;

        Method eat = clazz.getDeclaredMethod("eat", String.class);

        eat.setAccessible(true);

        Cat cat = new Cat();
        Object invoke = eat.invoke(cat, "🐟");
        System.out.println(invoke);
    }
}

案例:

/*
反射案例
    对于任意一个对象,该框架都可以把对象的字段名和对应的值,然后打印在控制台

*/
public class Demo5 {
    public static void main(String[] args) {
        //1. 准备两个对象
        Student student = new Student("柳岩", 40, '女', 167.5, "女星");
        Teacher teacher = new Teacher("播妞", 6000);

        //2.调用方法

        print(student);
    }

    public static void print(Object o)  {

        try {
            Class clazz = o.getClass();

            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields) {

                declaredField.setAccessible(true);

                String name = declaredField.getName();
                Object o1 = declaredField.get(o);
                System.out.println(name+o1);
            }
        }catch (Exception e){
        }

    }
}

class Student{
    public Student(String name, int age, char sex, double height, String hobby) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.height = height;
        this.hobby = hobby;
    }

    private String name;
    private int age;
    private char sex;
    private double height;
    private String hobby;
}

class Teacher {
    public Teacher(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    private String name;
    private double salary;
}

反射的作用

注解

元注解

        指的是:修饰注解的注解。 

注解解析器

 就是判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来。 

如何解析注解

public class ClassNameCheckParser {

    public static void checkClassName(){
        //1.存放不符合规范的类
        ArrayList<String> list = new ArrayList<>();

        //2.获取指定包下的所有类
        Set<Class> clazzSet = ClassUtil.getClasses("com.itheima.c_annotation.example");
        //3.遍历set集合找到标注@ClassNameCheck注解的类'

        for (Class clazz : clazzSet) {

            //判断某个类上是否有某个注解
            if(clazz.isAnnotationPresent(ClassNameCheck.class)){

                //获得类名
                String simpleName = clazz.getSimpleName();
                //检查类名是否以Heima开头
                if(!simpleName.startsWith("Hei")){

                    list.add(simpleName);
                }
            }
        }

        //判断集合中是否有不符合规范的,如果有直接保存
        if(list.size() > 0) {

            System.out.println("下面类名不符合规范");
            for (String name : list) {
                System.out.println(name);
            }
            throw new RuntimeException("程序终止");
        }

    }

}

本文转载自: https://blog.csdn.net/m0_60388241/article/details/134125894
版权归原作者 IT_Rocter 所有, 如有侵权,请联系我们删除。

“单元测试&反射&注解”的评论:

还没有评论