day13-单元测试&反射&注解

一、单元测试

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

1.1 Junit单元测试框架

    可以用来对方法进行测试,它是由Junit公司开源出来的
优点
    可以灵活的编写测试代码,可以针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立。
    不需要程序员去分析测试的结果,会自动生成测试报告出来。
    
1、Junit单元测试是做什么的?
    测试类中方法的正确性的
2、JUnit单元测试的实现过程是什么样的?
    必须导入Junit框架的jar包
    定义的测试方法必须是无参数无返回值,且公开的方法
    测试方法使用@Test注解标记
3、JUnit测试某个方法,测试全部方法怎么处理?成功的标志是什么?
    测试某个方法直接右键该方法启动测试
    测试全部方法,可以选择类或者模块启动
    红色失败,黄色警告,绿色通过

需求

某个系统,有多个业务方法,请使用Junit单元测试框架,编写测试代码,完成对这些方法的正确性测试。

具体步骤

①将Junit框架的jar包导入到项目中(资料中已经提供)

②为需要测试的业务类,定义对应的测试类,并为每个业务方法,编写对应的测试方法(必须:公共、无参、无返回值)

③测试方法上必须声明@Test注解,然后在测试方法中,编写代码调用被测试的业务方法进行测试;

④开始测试:选中测试方法,右键选择“JUnit运行” ,如果测试通过则是绿色;如果测试失败,则是红色

public class StringUtil {
​
    //获取字符串长度
    public static void printNumber(String name) {
        System.out.println("名字长度:" + name.length());
    }
}
​
public class StringUtilTest {
    @Test
    public void testprintNumber(){
        //printNumber为静态方法, 直接用类StringUtil调用
        StringUtil.printNumber("hello");
        StringUtil.printNumber("123");
        StringUtil.printNumber("");
        StringUtil.printNumber(null);//异常:java.lang.NullPointerException空指针异常
    }
}

1.1.1 断言

public class StringUtil {
    //获取字符串的最大索引
    public int getMaxIndex(String data) {
        if (data == null) {
            return -1;
        }
        return data.length();
    }
}
​
public class StringUtilTest {
    @Test
    public void testGetMaxIndex(){
        //创建对象
        StringUtil stringUtil = new StringUtil();
        //调用方法
        int index1 = stringUtil.getMaxIndex("hello");
        Assert.assertEquals("最大索引不符合预期",4, index1);//断言:会影响后面的程序执行
​
        int index2 = stringUtil.getMaxIndex("123");
        Assert.assertEquals("最大索引不符合预期",3, index2);//预期相同,打印台不会有东西输出
​
        int index3 = stringUtil.getMaxIndex("李四");
        int index4 = stringUtil.getMaxIndex("");
        int index5 = stringUtil.getMaxIndex(null);
    }
}

 

1.2 Junit框架的常见注解

Junit 4.xxxx版本

注解说明
@Test测试类中的方法必须用它修饰才能成为测试方法,才能启动执行
@Before用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。
@After用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。
@BeforeClass用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。
@AfterClass用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。

在测试方法执行前执行的方法,常用于:初始化资源。

在测试方法执行完后再执行的方法,常用于:释放资源。

/**
 * 测试类的初始化代码
 * 每个测试执行开始前,调用
 */
@Before
public void init(){
    System.out.println("调用init方法");
}
​
/**
 * 每个测试执行结束时调用
 */
@After
public void end(){
    System.out.println("测试方法执行结束");
}
​
/**
 * 测试类的初始化代码
 * 在所有测试方法之前只执行一次。
 */
@BeforeClass
public static void BeforeClass(){
    System.out.println("调用BeforeClass方法");
}
​
/**
 * 在所有测试方法之后前只执行一次。
 */
@AfterClass
public static void AfterClass(){
    System.out.println("AfterClass测试方法执行结束");
}

Junit 5.xxxx版本

注解说明
@Test测试类中的方法必须用它修饰才能成为测试方法,才能启动执行
@BeforeEach用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。
@AfterEach用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。
@BeforeAll用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。
@AfterAll用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次。

开始执行的方法:初始化资源

执行完之后的方法:释放资源

二、反射

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

定义一个Cat类用于下面的测试
​
public class Cat {
    public static int a;
    public static final String COUNTRY = "中国";
    private String name;
    private int age;
​
    public Cat(){
        System.out.println("无参数构造器执行了~~");
    }
​
    public Cat(String name) {
        this.name = name;
    }
​
    private Cat(String name, int age) {
        System.out.println("有参数构造器执行了~~");
        this.name = name;
        this.age = age;
    }
​
    private void run(){
        System.out.println("🐱跑的贼快~~");
    }
​
    public void eat(){
        System.out.println("🐱爱吃猫粮~");
    }
​
    private String eat(String name){
        return "🐱最爱吃:" + name;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    public int getAge() {
        return age;
    }
​
    public void setAge(int age) {
        this.age = age;
    }
​
    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

 

2.1 获取类

反射的第一步是什么
    获取Class类对象,如此才可以解析类的全部成分
​
获取Class对象的三种方式
    1. 直接使用类名.class获取:Class c1 = 类名.class
    2. 调用Class提供的方法:Class c2 = Class.forName("全类名":包名+类名)
    3. 调用Object提供的方法:Class c3 = 对象.getClass()

public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1. 直接使用类名.class获取:Class c1 = 类名.class
        Class<Cat> c1 = Cat.class;
        System.out.println(c1);//class com.wt.b_反射.Cat
        // 2. 调用Class提供的方法:Class c2 = Class.forName("全类名")
        Class<?> c2 = Class.forName("com.wt.b_反射.Cat");
        System.out.println(c2);//class com.wt.b_反射.Cat
​
        // 3. 调用Object提供的方法:Class c3 = 对象.getClass()
        Cat cat = new Cat();
        Class<? extends Cat> c3 = cat.getClass();// 获取对象的运行类型
        System.out.println(c3);//class com.wt.b_反射.Cat
        System.out.println("==============");
        System.out.println(c3.getName());//com.wt.b_反射.Cat
        System.out.println(c3.getSimpleName());//Cat
        System.out.println(c3.getPackage().getName());//com.wt.b_反射
        System.out.println(c3.getSuperclass());//class java.lang.Object
       
    }
}

2.2 获取构造器

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,表示禁止检查访问控制(暴力反射)
获取构造器[下面是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 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1.获取类class对象
        Class<Cat> catClass = Cat.class;
        // Constructor<?>[] getConstructors()  获取所有的公共构造器(只能获取public修饰的)
        Constructor<?>[] constructors = catClass.getConstructors();
        int length = constructors.length;
        System.out.println("公共的构造器个数:" + length);//1(只有一个公共的构造器)
        System.out.println("===============");
​
        // Constructor<?>[] getDeclaredConstructors()  获取全部构造器(只要存在就能拿到)
        Constructor<?>[] declaredConstructors = catClass.getDeclaredConstructors();
        System.out.println("全部构造器个数:" +declaredConstructors.length);
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("构造器参数名字:"+declaredConstructor.getName());//Cat()
            System.out.println("构造器参数个数:"+declaredConstructor.getParameterCount());
        }
        System.out.println("===============");
​
        // Constructor<T> getConstructor(Class<?>... parameterTypes)   获取某个公共构造器(只能获取public修饰的)
        Constructor<Cat> constructor = catClass.getConstructor();
        System.out.println("公共构造器为:"+constructor);//公共构造器为:public com.wt.b_反射.Cat()
        Constructor<Cat> constructor1 = catClass.getConstructor(String.class);
        System.out.println("构造器为:"+constructor1);//构造器为:public com.wt.b_反射.Cat(java.lang.String)
        System.out.println("===============");
​
        // Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)   获取某个构造器(只要存在就能拿到)
        Constructor<Cat> declaredConstructor = catClass.getDeclaredConstructor(String.class, int.class);
        System.out.println("构造器为:"+declaredConstructor);//构造器为:private com.wt.b_反射.Cat(java.lang.String,int)
        System.out.println("构造器的参数个数为:"+declaredConstructor.getParameterCount());//构造器的参数个数为:2
        System.out.println("===================");
​
        //创建Cat对象,使用构造器对象,公共无参
        Constructor<Cat> constructor3 = catClass.getConstructor();
        Cat cat1 = constructor3.newInstance();
        System.out.println(cat1);//Cat{name='null', age=0}
        System.out.println("===================");
​
        //创建Cat对象,使用构造器对象,私有有参
        //IllegalAccessException:访问控制异常,因为反射创建对象时,默认是禁止访问控制,所以需要使用暴力反射
        Constructor<Cat> declaredConstructor2 = catClass.getDeclaredConstructor(String.class, int.class);
        declaredConstructor2.setAccessible(true);
        Cat cat2 = declaredConstructor2.newInstance("小花", 2);
        System.out.println(cat2);//Cat{name='小花', age=2}
​
​
    }
}

2.3 获取成员变量

Class提供了从类中获取成员变量的方法

方法说明
public Field[] getFields()获取类的所有公共成员变量(只能获取public修饰的)
public Field[] getDeclaredFields()获取类的全部成员变量(只要存在就能拿到)
public Field getField(String name)获取类的某个公共成员变量(只能获取public修饰的)
public Field getDeclaredField(String name)获取类的某个成员变量(只要存在就能拿到)

获取到成员变量的作用:依然是赋值、取值

Field的方法说明
public void set(Object obj, Object value)赋值
public Object get(Object obj)取值
public void setAccessible(boolean flag)设置为true,表示禁止检查访问控制(暴力反射)
获取成员变量[Class提供]
    public Field[] getFields() 获取类的所有公共成员变量(只能获取public修饰的)
    public Field[] getDeclaredFields() 获取类的全部成员变量(只要存在就能拿到)
    public Field getField(String name) 获取类的某个公共成员变量(只能获取public修饰的)
    public Field getDeclaredField(String name) 获取类的某个成员变量(只要存在就能拿到)
​
使用成员变量(赋值和取值) [Field提供]
    public void set(Object obj, Object value): 赋值
    public Object get(Object obj): 取值
    public void  setAccessible(boolean flag):  设置为true,表示禁止检查访问控制(暴力反射)
​
注意
    使如果想使用private修饰的变量,需要暴力反射
public class Demo3 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //1.获取类class对象
        Class<Cat> catClass = Cat.class;
        // public Field[] getFields()  获取类的所有公共成员变量(只能获取public修饰的)
        Field[] fields = catClass.getFields();
        System.out.println("公共成员变量个数:"+fields.length);//公共成员变量个数:2
        for (Field field : fields) {
            System.out.println("成员变量"+field);
            System.out.println("成员变量类型:"+field.getType());
            System.out.println("成员变量名:"+field.getName());
            System.out.println("===================");
        }
        System.out.println();
​
        // public Field[] getDeclaredFields()  获取类的全部成员变量(只要存在就能拿到)
        Field[] declaredFields = catClass.getDeclaredFields();
        System.out.println("全部成员变量个数:"+declaredFields.length);//全部成员变量个数:4
        for (Field declaredField : declaredFields) {
            System.out.println("成员变量:"+declaredField);
            System.out.println("成员变量类型:"+declaredField.getType());
            System.out.println("成员变量名:"+declaredField.getName());
            System.out.println("===================");
        }
        System.out.println();
​
        // public Field getDeclaredField(String name)  获取类的某个成员变量(只要存在就能拿到)
        Field aField = catClass.getDeclaredField("a");
        System.out.println("aField:"+aField.getName() + " " + aField.getType());//aField:a int
        Field nameField = catClass.getDeclaredField("name");
        System.out.println("nameField:"+nameField.getName()  + " " + nameField.getType());//nameField:name class java.lang.String
        Field counField = catClass.getDeclaredField("COUNTRY");
        System.out.println("counField:"+counField.getName() + " " + counField.getType());//counField:COUNTRY class java.lang.String
​
        System.out.println("===================");
​
        // 使用成员变量(赋值和取值) [Field提供]
        //1.1 创建对象
        Cat cat = new Cat();
        int a = (int)aField.get(cat);
        System.out.println("a的值为:"+a);//a的值为:0
        aField.set(cat,100);
        int a1 = (int)aField.get(cat);
        System.out.println("a1的值为:"+a1);//a1的值为:100
​
​
        String country = (String) counField.get(cat);
        System.out.println("country的值为:"+country);//country的值为:中国
​
        nameField.setAccessible(true);
        String name = (String) nameField.get(cat);//报错IllegalAccessException:访问权限被拒绝,name为私有变量,需要暴力反射
        System.out.println("name的值为:"+ name);//name的值为:null
        nameField.set(cat,"小花");
        String name1 = (String) nameField.get(cat);
        System.out.println("name1的值为:"+ name1);//name1的值为:小花
​
    }
}

2.4 获取成员方法

Class提供了从类中获取成员方法的API

方法说明
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,表示禁止检查访问控制(暴力反射)
获取成员方法[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 {
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.获取类class对象
        Class<Cat> catClass = Cat.class;
        // Method[] getMethods()   获取类的全部公共成员方法(只能获取public修饰的)
        Method[] method = catClass.getMethods();
        System.out.println("全部公共成员方法个数:"+method.length);
        for (Method method1 : method) {
            System.out.println("============");
            System.out.println("方法名字:"+method1.getName() + "  参数个数:"+method1.getParameterCount()
                    + " 返回值类型:" + method1.getReturnType());
        }
        System.out.println();
​
        // Method[] getDeclaredMethods()   获取类的全部成员方法(只要存在就能拿到)
        Method[] declaredMethod = catClass.getDeclaredMethods();
        System.out.println("全部成员方法个数:"+declaredMethod.length);
        for (Method method1 : declaredMethod) {
            System.out.println("============");
            System.out.println("方法名字:"+method1.getName() + "  参数个数:"+method1.getParameterCount()
                    + " 返回值类型:" + method1.getReturnType());
        }
        System.out.println();
​
        // Method getMethod(String name, Class<?>... parameterTypes)   获取类的某个公共成员方法(只能获取public修饰的)
​
        // Method getDeclaredMethod(String name, Class<?>... parameterTypes)   获取类的某个成员方法(只要存在就能拿到)
        Method method1 = catClass.getDeclaredMethod("eat", String.class);
        System.out.println("方法名字:"+method1.getName() + "  参数个数:"+method1.getParameterCount()
                + " 返回值类型:" + method1.getReturnType());
​
        // 使用成员方法(执行方法)
        //创建对象
        Cat cat = new Cat();
        method1.setAccessible(true);
       String  str = (String) method1.invoke(cat, "猫粮");
        System.out.println(str);
​
    }
​
}
​
运行结果:
全部成员方法个数:8
============
方法名字:getName  参数个数:0 返回值类型:class java.lang.String
============
方法名字:run  参数个数:0 返回值类型:void
============
方法名字:toString  参数个数:0 返回值类型:class java.lang.String
============
方法名字:setName  参数个数:1 返回值类型:void
============
方法名字:setAge  参数个数:1 返回值类型:void
============
方法名字:getAge  参数个数:0 返回值类型:int
============
方法名字:eat  参数个数:1 返回值类型:class java.lang.String
============
方法名字:eat  参数个数:0 返回值类型:void
​
方法名字:eat  参数个数:1 返回值类型:class java.lang.String
无参数构造器执行了~~
🐱最爱吃:猫粮

2.5 反射的作用

基本作用
    可以得到一个类的全部成分然后操作。
    可以破坏封装性,也可以破坏泛型的约束性。
最重要的用途是
    适合做Java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能。
反射案例
    对于任意一个对象,该框架都可以把对象的字段名和对应的值,然后打印在控制台
​
    实现步骤
        定义一个方法,可以接收任意对象
        每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量
        遍历成员变量,然后提取成员变量在该对象中的具体值
        把成员变量名、和其值,打印到控制台即可
public class Demo5 {
    public static void main(String[] args) throws IllegalAccessException {
        //1. 准备两个对象
        Student student = new Student("柳岩", 40, '女', 167.5, "女星");
        Teacher teacher = new Teacher("播妞", 6000);
​
        //2.调用方法
        printObject(student);
        printObject(teacher);
​
    }
    
    // 定义一个方法,可以接收任意对象
    public static void printObject(Object obj) throws IllegalAccessException {
        //1. 获取对象的Class对象
        Class<?> clazz = obj.getClass();
        //1.2 获取类的名字
        String simpleName = clazz.getSimpleName();
        System.out.println("=======================" + simpleName + "=======================");
        //2. 获取全部的成员变量
        Field[] declaredFields = clazz.getDeclaredFields();
​
        //3. 遍历全部的成员变量
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);//暴力反射
            //4. 获取成员变量名和对应的值
            String name = declaredField.getName();
            Object o = declaredField.get(obj);
            // 5. 打印到控制台
            System.out.println(name + "=" + o);
        }
    }
}
​
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;
}

三、注解Annotation

注解: 
    是Java代码里的特殊标记,比如:@Override、@Test等
    这些标记会被特定的注解解析器所发现,进而决定应该怎样去编译或者执行被注解标记出来的程序
    作用是对Java中类、方法、成员变量做标记,然后进行特殊处理

 

 

注解的解析:判断类上、方法上、成员变量上是否存在注解,并把注解里的内容给解析出来。
如何解析注解?
    指导思想:要解析谁上面的注解,就应该先拿到谁
    比如要解析类上面的注解,则应该先获取该类的Class对象,再通过Class对象解析其上面的注解
    比如要解析成员方法上的注解,则应该获取到该成员方法的Method对象,再通过Method对象解析其上面的注解
    Class 、 Method 、 Field , Constructor、都实现了AnnotatedElement接口,它们都拥有解析注解的能力
​
    
AnnotatedElement接口提供了解析注解的方法说明
public Annotation[] getDeclaredAnnotations()获取当前对象上面的注解。
public T getDeclaredAnnotation(Class<T> annotationClass)获取指定的注解对象
public boolean isAnnotationPresent(Class<Annotation> annotationClass)判断当前对象上是否存在某个注解

解析注解的案例

需求如下

定位到指定包中所有带@ClassNameCheck注解的类,然后判断类名是否是以Heima开头,如果不是,就抛异常

下面分析一下步骤

①定义一个类叫ClassNameCheckParser,在类中定义一个checkClassName方法,用来完成功能

②获取项目中指定包下的所有类(此功能已经在工具类中提供好了方法,可以直接使用)

③遍历得到每一个类,然后判断类上是否有@ClassNameCheck注解

④如果有注解,则获取到类名进行判断,如果不符合规范,则放到一个准备好的集合中

⑤等到遍历结束,查看集合中是否有元素;有就说明存在不符合规范的类名;打印结果,抛出异常

public class ClassNameCheckParse {
    public void CheckClassName(){
        //创建一个集合,用于存放不符合规范的类名
        HashSet<String> nameSet = new HashSet<>();
        //传入包的名字,获取包下的所有类对象的集合
        Set<Class> classSet = ClassUtil.getClasses("com.itheima.c_annotation.example");
        //遍历类,判断是否有ClassNameCheck注解
        for (Class clazz : classSet) {
            //判断类对象上是否有注解
            boolean b = clazz.isAnnotationPresent(ClassNameCheck.class);
            if(b){
                //获取类的名字
                String className = clazz.getSimpleName();
                //判断类名是否符合规范,以“Hema”开头,如果不符合,就放入集合
                if(!className.startsWith("Hema")){
                    nameSet.add(className);
                }
            }
        }
        //判断集合是否为空,如果不为空,就打印并抛出异常
        if(nameSet.size()>0){
            for (String name : nameSet) {
                System.out.println("不符合规范的类名:"+name);
            }
            throw new RuntimeException("类名不符合规范");
        }
    }
}

 

解析注解的案例改进

需求如下:

在定位到有问题的类名的时候,要打印出类的开发者和作用

下面分析一下步骤

①修改@ClassNameLimit注解,添加author和value属性

②修改解析器的类,解析出代码的开发者和作用,并打印出来

public class ClassNameCheckParse {
    public void CheckClassName(){
        //创建一个集合,用于存放不符合规范的类名
        HashSet<String> nameSet = new HashSet<>();
        //传入包的名字,获取包下的所有类对象的集合
        Set<Class> classSet = ClassUtil.getClasses("com.itheima.c_annotation.example");
        //遍历类,判断是否有ClassNameCheck注解
        for (Class clazz : classSet) {
            //判断类对象上是否有注解
            boolean b = clazz.isAnnotationPresent(ClassNameCheck.class);
            if(b){
                //获取类的名字
                String className = clazz.getSimpleName();
                //判断类名是否符合规范,以“Heima”开头,如果不符合,就放入集合
                if(!className.startsWith("Heima")){
                   //使用反射获取注解对象
                    ClassNameCheck cnc = (ClassNameCheck)clazz.getDeclaredAnnotation(ClassNameCheck.class);
                    //使用注解对象的value属性,获取注解的属性值
                    String[] author = cnc.author();
                    String value = cnc.value();
                    nameSet.add(className + ",作者:" + Arrays.toString(author) + ",作用:" + value);
                }
            }
        }
        //判断集合是否为空,如果不为空,就打印并抛出异常
        if(nameSet.size()>0){
            for (String name : nameSet) {
                System.out.println("不符合规范的类名:"+name);
            }
            throw new RuntimeException("类名不符合规范");
        }
    }
}

  • 24
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值