【Day13-单元测试&反射&注解】

 单元测试

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

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

  • 只能在main方法编写测试代码,去调用其他方法进行测试。
  • 无法实现自动化测试,一个方法测试失败,可能影响其他方法的测试。
  • 无法得到测试的报告,需要程序员自己去观察测试是否成功。

Junit单元测试框架

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

优点

  • 可以灵活的编写测试代码,可以针对某个方法执行测试,也支持一键完成对全部方法的自动化测试,且各自独立。
  • 不需要程序员去分析测试的结果,会自动生成测试报告出来。

 Junit单元测试-快速入门

 

package com.itheima.a_单元测试;

import org.junit.*;

public class StringUtilTest {
    /*===调用initClass方法===
    ===调用init方法===
    2
    ===测试方法调用结束===
    ===调用init方法===
    名字长度:5
    名字长度:3
    名字长度:0
    ===测试方法调用结束===
    ===endClass===
    */
    @Before
    //在测试方法执行前执行的方法,常用于:初始化资源。
    public void init() {
        System.out.println("===调用init方法===");
    }
    @After
    //在测试方法执行完后再执行的方法,常用于:释放资源。
    public void end() {
        System.out.println("===测试方法调用结束===");
    }
    @BeforeClass
    public static void initClass() {
        System.out.println("===调用initClass方法===");
    }
    @AfterClass
    public static void endClass() {
        System.out.println("===endClass===");
    }
    @Test
    public void testprintNumber() {
        //直接用类名调用
        StringUtil.printNumber("jacky");
        StringUtil.printNumber("李铁牛");
        StringUtil.printNumber("");
//        StringUtil.printNumber(null);
    }

    @Test
    public void testgetMaxIndex() {
        int maxIndex = new StringUtil().getMaxIndex("jacky");
//        Assert.assertEquals("最大索引不符合预期", 2, maxIndex);

        int maxIndex1 = new StringUtil().getMaxIndex("翠花");
        System.out.println(maxIndex1);
        int maxIndex2 = new StringUtil().getMaxIndex("");
        int maxIndex3 = new StringUtil().getMaxIndex(null);
    }
}
public class StringUtil {

    //获取字符串长度
    public static void printNumber(String name) {
        System.out.println("名字长度:" + name.length());
    }

    //获取字符串的最大索引
    public int getMaxIndex(String data) {
        if (data == null) {
            return -1;
        }
        return data.length();
    }
}

1Junit单元测试是做什么的?

测试类中方法的正确性的

2JUnit单元测试的实现过程是什么样的?

必须导入Junit框架的jar包

定义的测试方法必须是无参数无返回值,且公开的方法

测试方法使用@Test注解标记

3JUnit测试某个方法,测试全部方法怎么处理?成功的标志是什么

测试某个方法直接右键该方法启动测试

测试全部方法,可以选择类或者模块启动

红色失败,绿色通过 

Junit框架的常见注释

Junit单元测试框架的常用注解(Junit 4.xxxx版本)

注解

说明

@Test

测试类中的方法必须用它修饰才能成为测试方法,才能启动执行

@Before

用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。

@After

用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。

@BeforeClass

用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。

@AfterClass

用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次

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

Junit单元测试框架的常用注解(Junit 5.xxxx版本) 

注解

说明

@Test

测试类中的方法必须用它修饰才能成为测试方法,才能启动执行

@BeforeEach

用来修饰一个实例方法,该方法会在每一个测试方法执行之前执行一次。

@AfterEach

用来修饰一个实例方法,该方法会在每一个测试方法执行之后执行一次。

@BeforeAll

用来修饰一个静态方法,该方法会在所有测试方法之前只执行一次。

@AfterAll

用来修饰一个静态方法,该方法会在所有测试方法之后只执行一次

  • 开始执行的方法:初始化资源
  • 执行完之后的方法:释放资源

 反射

反射(Reflection 

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

 反射学什么?

 

获取Class对象的三种方式

  1. 直接使用类名.class获取:Class c1 = 类名.class
  2. 调用Class提供的方法:Class c2 = Class.forName("全类名")
  3. 调用Object提供的方法:Class c3 = 对象.getClass()
/*
反射的第一步是什么
    获取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> catClass = Cat.class;
        System.out.println(catClass);
        //2. 调用Class提供的方法:Class c2 = Class.forName("全类名")
        Class<?> aClass = Class.forName("com.itheima.b_反射.Cat");
        System.out.println(aClass);
        //3. 调用Object提供的方法:Class c3 = 对象.getClass()
        Cat cat = new Cat();
        Class<? extends Cat> aClass1 = cat.getClass();
        System.out.println(aClass1);
        System.out.println(aClass1.getName());
        System.out.println(aClass1.getSimpleName());
    }
}

1、反射的第一步是什么?

获取Class类对象,如此才可以解析类的全部成分

 2获取Class类对象的三种方式是啥?

Class c1 = 类名.class

Class c2 = Class.forName("全类名");

Class c3 = 对象.getClass();

获取类的构造器

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 {
        //创建获取类Class对象
        Class<Cat> catClass = Cat.class;
        //Constructor<?>[] getConstructors()	获取所有的公共构造器(只能获取public修饰的)
        Constructor<?>[] constructors = catClass.getConstructors();
        System.out.println(constructors.length);
        //Constructor<?>[] getDeclaredConstructors()	获取全部构造器(只要存在就能拿到)
        Constructor<?>[] declaredConstructors = catClass.getDeclaredConstructors();
        System.out.println(declaredConstructors);
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor.getName());
            System.out.println(declaredConstructor.getParameterCount());
        }
        //Constructor<T> getConstructor(Class<?>... parameterTypes)	获取某个公共构造器(只能获取public修饰的)
        Constructor<Cat> constructor = catClass.getConstructor();
        System.out.println(constructor.getParameterCount());
        Constructor<Cat> constructor1 = catClass.getConstructor(String.class);
        System.out.println(constructor1.getParameterCount());
//        Constructor<Cat> constructor2 = catClass.getConstructor(int.class, String.class);//NoSuchMethodException,没有得不到这个参数构造器
//        System.out.println(constructor2.getParameterCount());
        //Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)	获取某个构造器(只要存在就能拿到)
        Constructor<Cat> declaredConstructor = catClass.getDeclaredConstructor(String.class, int.class);
        System.out.println(declaredConstructor.getParameterCount());

        //创建Cat对象,使用构造器对象,公共无参
        Cat cat = constructor.newInstance();
        System.out.println(cat);

        System.out.println("============");
        //使用私有构造器对象,创建对象
        //暴力反射
        declaredConstructor.setAccessible(true);
        Cat cat1 = declaredConstructor.newInstance("狸花猫", 2);
        System.out.println(cat1);
    }

}

1、如何去获取类的构造器?

Constructor<?>[] getDeclaredConstructors​()

Constructor<T> getDeclaredConstructor​(Class<?>... parameterTypes)

2、获取到类的构造器,有啥作用?

T newInstance​(Object... initArgs)

public void  setAccessible(boolean flag) 

获取类的成员变量 

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 {
        //第一步,获取Class对象
        Class<Cat> catClass = Cat.class;
        //    public Field[] getFields()	获取类的所有公共成员变量(只能获取public修饰的)
        //    public Field[] getDeclaredFields()	获取类的全部成员变量(只要存在就能拿到)
        Field[] declaredFields = catClass.getDeclaredFields();
        System.out.println("变量个数=" + declaredFields.length);
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName() + ",类型" + declaredField.getType());
        }
        //    public Field getField(String name)	获取类的某个公共成员变量(只能获取public修饰的)
        //    public Field getDeclaredField(String name)	获取类的某个成员变量(只要存在就能拿到)
        Field aField = catClass.getDeclaredField("a");
        System.out.println(aField.getName() + "-" + aField.getType());
        Field nameField = catClass.getDeclaredField("name");
        System.out.println(nameField.getName() + "-" + nameField.getType());
        Field countryField = catClass.getDeclaredField("COUNTRY");
        System.out.println(countryField.getName() + "-" + countryField.getType());

        //创建对象
        Cat cat = new Cat();
        System.out.println(cat);
        int a = (int) aField.get(cat);
        System.out.println(a);

        String country = (String) countryField.get(cat);
        System.out.println(country);

        //暴力反射 需要获取私有参数
        nameField.setAccessible(true);
        String name = (String) nameField.get(cat);
        System.out.println(name);

        aField.set(cat,88);
        int a1 = (int) aField.get(cat);
        System.out.println(a1);

        nameField.set(cat,"丧彪");
        String name1 = (String) nameField.get(cat);
        System.out.println(name1);
    }
}

1、如何去获取类的成员变量?

getDeclaredFields()

getDeclaredField (String name)

2、获取到类的成员变量,有啥作用?

void set​(Object obj, Object value)

Object get​(Object obj)

setAccessible(boolean) 

获取类的成员方法

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 {
        Class<Cat> catClass = Cat.class;
        Method[] declaredMethods = catClass.getDeclaredMethods();
        //有几个方法
//        System.out.println(declaredMethods.length);
        //每个方法的名字和返回类型
//        for (Method declaredMethod : declaredMethods) {
//            System.out.println("方法名字:" + declaredMethod.getName() + "返回类型:" + declaredMethod.getReturnType());
//        }
        Method eatMethod = catClass.getDeclaredMethod("eat", String.class);
        System.out.println(eatMethod.getReturnType());//class java.lang.String 得到私有方法
        //得到该方法中的参数类型
        Class<?>[] parameterTypes = eatMethod.getParameterTypes();
//        for (Class<?> parameterType : parameterTypes) {
//            System.out.println(parameterType.getName());
//        }

        Cat cat = new Cat();
        //暴力反射
        eatMethod.setAccessible(true);
        String str = (String) eatMethod.invoke(cat, "巴西果冻");
        System.out.println(str);
    }
}

反射的作用? 

  • 基本作用:可以得到一个类的全部成分然后操作。
  • 可以破坏封装性。
  • 重要的用途是适合做Java框架基本上主流框架都会基于反射设计一些通用功能。

 案例:

实现步骤

  1. 定义一个方法,可以接收任意对象
  2. 每收到一个对象后,使用反射获取该对象的Class对象,然后获取全部的成员变量
  3. 遍历成员变量,然后提取成员变量在该对象中的具体值
  4. 把成员变量名、和其值,打印到控制台即可 
/*
反射案例
    对于任意一个对象,该框架都可以把对象的字段名和对应的值,然后打印在控制台

*/
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.调用方法
        printObj(student);
        printObj(teacher);
    }

    public static void printObj(Object obj) throws IllegalAccessException {
        Class<?> clazz = obj.getClass();
        String name = clazz.getSimpleName();
        System.out.println("===========" + name + "===========");
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.setAccessible(true);
            System.out.println(declaredField.getName() + "=" + declaredField.get(obj));
        }
    }
}

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;
}
1. 反射有啥作用?
  • 可以在运行时得到一个类的全部成分然后操作
  • 可以破坏封装性
  • 也可以破坏泛型的约束性
  • 更重要的用途是适合:做Java高级框架
  • 基本上主流框架都会基于反射设计一些通用技术功能

 注解(Annotation

  • 就是Java代码里的特殊标记,比如:@Override@Test
  • 这些标记会被特定的注解解析器所发现,进而决定应该怎样去编译或者执行被注解标记出来的程序

自定义注解格式

注解本质是一个接口,Java中所有注解都是继承了Annotation接口的。 

 元注解 

指的是:修饰注解的注解,可以指定注解的标注位置和保留阶段 

@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})//标记作用的位置
@Retention(RetentionPolicy.RUNTIME)//标记存货阶段
public @interface ClassNameCheck {
    public String[] author() default "heihei";
    public String value() ;
}

 什么是注解的解析?

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

 如何解析注解?

  • 指导思想:要解析谁上面的注解,就应该先拿到谁
  • 比如要解析类上面的注解,则应该先获取类的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(author = "heiyang",value = "simida")
public class Teacher {

    private String name;
    private Integer age;

    public String sayHello() {
        return "hello";
    }


}
//ClassNameCheckParse类
public class ClassNameCheckParse {

    public void checkClassName() {
        //创建存放不符合要求的类名的集合
        Set<String> nameSet = new HashSet<>();
        //传入包名字,获取包下的所有类对象集合
        Set<Class> clazzSet = ClassUtil.getClasses("com.itheima.c_annotation.example");
        for (Class clazz : clazzSet) {
            boolean flag = clazz.isAnnotationPresent(ClassNameCheck.class);
            if (flag) {
                //获取类名字
                String className = clazz.getSimpleName();
                //判断类名字是否符合规范,如果不符合,就放入集合
                if (!className.startsWith("Heima")) {
                    //使用反射获取,注解对象
                    ClassNameCheck cnc = (ClassNameCheck) clazz.getDeclaredAnnotation(ClassNameCheck.class);
                    //使用注解对象获取属性值
                    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("类名不符合规范");
        }
    }
}
//自定义注释
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})//标记作用的位置
@Retention(RetentionPolicy.RUNTIME)//标记存货阶段
public @interface ClassNameCheck {
    public String[] author() default "诸葛马懿";
    public String value() ;
}
//Class工具类
public class ClassUtil {
    private ClassUtil() {
    }


    /**
     * 获取某个包下的所有类
     */
    public static Set<Class> getClasses(String packageName) {
        try {
            Set<Class> classSet = new HashSet<>();
            Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageName.replace(".", "/"));
            while (urls.hasMoreElements()) {
                URL url = urls.nextElement();
                if (url != null) {
                    String protocol = url.getProtocol();
                    if (protocol.equals("file")) {
                        String packagePath = url.getPath().replaceAll("%20", " ");
                        addClass(classSet, packagePath, packageName);
                    } else if (protocol.equals("jar")) {
                        JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
                        if (jarURLConnection != null) {
                            JarFile jarFile = jarURLConnection.getJarFile();
                            if (jarFile != null) {
                                Enumeration<JarEntry> jarEntries = jarFile.entries();
                                while (jarEntries.hasMoreElements()) {
                                    JarEntry jarEntry = jarEntries.nextElement();
                                    String jarEntryName = jarEntry.getName();
                                    if (jarEntryName.endsWith(".class")) {
                                        String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
                                        doAddClass(classSet, className);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return classSet;
        } catch (Exception e) {
            throw new RuntimeException("包名错误");
        }


    }

    private static void addClass(Set<Class> classSet, String packagePath, String packageName) {
        File[] files = new File(packagePath).listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
            }
        });
        for (File file : files) {
            String fileName = file.getName();
            if (file.isFile()) {
                String className = fileName.substring(0, fileName.lastIndexOf("."));
                if (StringUtils.isNotEmpty(packageName)) {
                    className = packageName + "." + className;
                }
                doAddClass(classSet, className);
            } else {
                String subPackagePath = fileName;
                if (StringUtils.isNotEmpty(packagePath)) {
                    subPackagePath = packagePath + "/" + subPackagePath;
                }
                String subPackageName = fileName;
                if (StringUtils.isNotEmpty(packageName)) {
                    subPackageName = packageName + "." + subPackageName;
                }
                addClass(classSet, subPackagePath, subPackageName);
            }
        }
    }

    /**
     * 加载类
     */
    private static Class loadClass(String className, boolean isInitialized) {
        Class cls;
        try {
            cls = Class.forName(className, isInitialized, getClassLoader());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
        return cls;
    }

    /**
     * 加载类(默认将初始化类)
     */
    private static Class loadClass(String className) {
        return loadClass(className, true);
    }

    private static void doAddClass(Set<Class> classSet, String className) {
        Class cls = loadClass(className, false);
        classSet.add(cls);
    }
}
//测试类
public class Test {
    public static void main(String[] args) {
        ClassNameCheckParse parse = new ClassNameCheckParse();
        parse.checkClassName();


        System.out.println("吃饱了!");
    }
}

注解属性

  • 在定义注解的时候,还可以通过属性来进一步描述注解的细节 

 

特殊属性名: value 

  • 如果注解中只有一个value属性使用注解时,value名称可以不写!! 
@ClassNameCheck(author = {"heiyang","wudi"},value = "simida")
public class Teacher {

    private String name;
    private Integer age;

    public String sayHello() {
        return "hello";
    }


}
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})//标记作用的位置
@Retention(RetentionPolicy.RUNTIME)//标记存货阶段
public @interface ClassNameCheck {
    public String[] author() default "zrn";
    public String value() ;
}

 解析注解的案例改进

需求如下:

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

下面分析一下步骤:

修改 @ClassName Check 注解 , 添加author和value属性
修改解析器的类 ,解析出代码的开发者和作用 并打印出来
//测试类 ,也用上边的文件完成
public class Test {
    public static void main(String[] args) {

        Student student = new Student();
        student.setName("芜湖~");
        System.out.println(student.getName());

        System.out.println("吃饱了!");
    }
}

Lombok 

  • Lombok是一个实用的Java类库,能通过注解的形式自动生成构造器、getter/setterequalshashcodetoString等方法,并可以自动化生成日志变量,简化java开发、提高效率。 

 

注解

                                                                              作用

@Getter/@Setter

为所有的属性提供get/set方法

@ToString

会给类自动生成易阅读的 toString 方法

@EqualsAndHashCode

根据类所拥有的非静态字段自动重写 equals 方法和 hashCode 方法

@Data

提供了更综合的生成代码功能(@Getter + @Setter + @ToString + @EqualsAndHashCode

@NoArgsConstructor

为实体类生成无参的构造器方法

@AllArgsConstructor

为实体类生成除了static修饰的字段之外带有各参数的构造器方法。

注意:Lombok会在编译时,自动生成对应的java代码。我们使用lombok时,还需要安装一个lombok的插件(idea自带) 

@Data//get和set方法
@NoArgsConstructor//无参构造
@AllArgsConstructor//全参构造
@ClassNameCheck(author = {"baima","lvma"},value = "哇哈哈")
public class Student {

    private String name;
    private Integer age;

    public String sayHello() {
        return "hello";
    }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值