1 自定义注解

1.1 介绍

常用的功能集成一个注解功能。

1.2 API说明

  • ElementType:作用域,在下面类型的地方起作用,其他地方无效
    • TYPE:允许被修饰的注解作用在类、接口和枚举上
    • FIELD:允许作用在属性字段上
    • METHOD:允许作用在方法上
    • PARAMETER:允许作用在方法参数上
    • CONSTRUCTOR:允许作用在构造器上
    • LOCAL_VARIABLE:允许作用在本地局部变量上
    • ANNOTATION_TYPE:允许作用在注解上
    • PACKAGE:允许作用在包上
  • RetentionPolicy:注解的生命周期
    • SOURCE:当前注解编译期可见,不会写入 class 文件
    • CLASS:类加载阶段丢弃,会写入 class 文件
    • RUNTIME:永久保存,可以反射获取
  • @Target:修饰对象范围
    • 格式:@Target({ElementType.TYPE,ElementType,METHOD})
  • @Retention:保留时间
    • 格式:@Retention(RetentionPolicy.SOURCE)
  • @Inherited:允许子类继承
  • @Documented:生成javadoc文档信息

    1.3 使用

  • 自定义注解格式:

    1. public @interface 注解名{
    2. // 定义体
    3. }
  • 获取注解信息

  1. 获取当前类上的注解

    1. Class<?> aClass = Class.forName("com.mayikt.entity.UserEntity");
    2. MayiktName declaredAnnotation = aClass.getDeclaredAnnotation(MayiktName.class);
    3. System.out.println(declaredAnnotation);
  2. 获取当前方法上的注解

    1. Method userNameMethod = aClass.getDeclaredMethod("getUserName");
    2. MayiktName declaredAnnotation = userNameMethod.getDeclaredAnnotation(MayiktName.class);
    3. System.out.println(declaredAnnotation);
  3. 获取字段上的注解

    1. Field pubUserName = aClass.getDeclaredField("pubUserName");
    2. final MayiktName declaredAnnotation = pubUserName.getDeclaredAnnotation(MayiktName.class);
    3. System.out.println(declaredAnnotation);
  4. 获得构造方法注解

    1. // 先获得构造方法对象
    2. Constructor<TestAnnotation> constructors = aClass.getConstructor(new Class[] {});
    3. MyConstructorAnnotation myConstructorAnnotation = constructors.getAnnotation(MyConstructorAnnotation.class);// 拿到构造方法上面的注解实例
    4. System.out.println(myConstructorAnnotation.desc() + "+" + myConstructorAnnotation.uri());

    1.4 常用案例

    1.4.1 获取字段描述与字段长度

  • 自定义注解

    1. @Target(ElementType.FIELD) // 注解用于字段上
    2. @Retention(RetentionPolicy.RUNTIME) // 保留到运行时,可通过注解获取
    3. public @interface MyFeild{
    4. /**
    5. * 描述字段作用
    6. */
    7. String description();
    8. /**
    9. * 字段长度
    10. */
    11. int length();
    12. }
  • 实现注解和测试注解

    1. public class AnnoTest {
    2. // 使用我们的自定义注解
    3. @MyField(description = "用户名", length = 12)
    4. private String username;
    5. @Test
    6. public void testMyField(){
    7. // 获取类模板
    8. Class c = AnnoTest.class;
    9. // 获取所有字段
    10. for(Field f : c.getDeclaredFields()){
    11. // 判断这个字段是否有MyField注解
    12. if(f.isAnnotationPresent(MyField.class)){
    13. // 拿到注解实例
    14. MyField annotation = f.getAnnotation(MyField.class);
    15. System.out.println("字段:[" + f.getName() + "], 描述:[" + annotation.description() + "], 长度:[" + annotation.length() +"]");
    16. }
    17. }
    18. }
    19. }
  • 结果

image.png

1.4.2 获取类的描述和方法的描述

  • 自定义注解

    1. // 注解的作用域
    2. @Target({ElementType.METHOD, ElementType.TYPE})
    3. // 注解的生命周期
    4. @Retention(RetentionPolicy.RUNTIME)
    5. // 允许子类继承
    6. @Inherited
    7. // 生成javadoc的时候生成注解的信息
    8. @Documented
    9. // @interface:使用@interface关键定义注解
    10. public @interface Description {
    11. // 注解的成员
    12. // 成员类型所限的,合法的类型包括原始数据类型及String、Class、Annotation、Enumeration
    13. String desc();
    14. String author();
    15. // 成员以无参无异常方式生命,可以用default为成员指定一个默认值
    16. int age() default 18;
    17. // 如果注解成员只有一个时,成员名必须取名未value(),在使用时可以忽略成员名和赋值号(=)
    18. // 注解可以没有成员,没有成员的注解成为标识注解
    19. }
  • 调用注解 ```java @Description(desc=”I am class annotation”, author=”hd”) public class TestDescription {

    @Description(desc=”I am method annotation”, author=”hd”) public String test(){

    1. return "red";

    }

}

  1. - 实现注解
  2. ```java
  3. /**
  4. * 解析注解
  5. * 通过反射获取类,函数或成员上的运行时注解信息,从而实现动态控制程序运行的逻辑
  6. *
  7. * 对于一个类或者接口来说,Class 类中提供了以下一些方法用于反射注解。
  8. getAnnotation:返回指定的注解
  9. isAnnotationPresent:判定当前元素是否被指定注解修饰
  10. getAnnotations:返回所有的注解
  11. getDeclaredAnnotation:返回本元素的指定注解
  12. getDeclaredAnnotations:返回本元素的所有注解,不包含父类继承而来的
  13. *
  14. * @author H__D
  15. * @date 2019-07-09 22:52:42
  16. *
  17. */
  18. public class ParseDecription {
  19. public static void main(String[] args) {
  20. // TODO Auto-generated method stub
  21. // 1、使用类加载器加载类
  22. try {
  23. Class c = Class.forName("com.xkcoding.test.TestDescription");
  24. System.out.println(c);
  25. // 2、找到类上面的注解
  26. boolean isExist = c.isAnnotationPresent(Description.class);
  27. if(isExist) {
  28. // 3、拿到注解实例
  29. Description d = (Description) c.getAnnotation(Description.class);
  30. System.out.println("========parse class annotation=========");
  31. System.out.println("desc = " + d.desc());
  32. System.out.println("author = " + d.author());
  33. System.out.println("age = " + d.age());
  34. }
  35. // 4、找到方法上的注解
  36. Method[] ms = c.getMethods();
  37. for (Method m : ms) {
  38. boolean isMExist = m.isAnnotationPresent(Description.class);
  39. if(isMExist) {
  40. Description d = m.getAnnotation(Description.class);
  41. System.out.println("========parse method annotation=========");
  42. System.out.println("desc = " + d.desc());
  43. System.out.println("author = " + d.author());
  44. System.out.println("age = " + d.age());
  45. }
  46. }
  47. // 另外一种解析方法
  48. for (Method m : ms) {
  49. Annotation[] annotations = m.getAnnotations();
  50. for (Annotation annotation : annotations) {
  51. if(annotation instanceof Description) {
  52. System.out.println("========parse method annotation other way=========");
  53. Description d = (Description) annotation;
  54. System.out.println("desc = " + d.desc());
  55. System.out.println("author = " + d.author());
  56. System.out.println("age = " + d.age());
  57. }
  58. }
  59. }
  60. } catch (ClassNotFoundException e) {
  61. // TODO Auto-generated catch block
  62. e.printStackTrace();
  63. }
  64. }
  65. }
  • 结果

image.png

2 常用注解

  • @Override:表示方法重写。
  • @Deprecated:表示过时的方法。
  • @SuppressWarnings:表示忽略警告。