• P03 注解


    系统:Win10
    Java:1.8.0_333
    IDEA:2020.3.4
    Gitee:https://gitee.com/lijinjiang01/JavaWeb

    1.注解概述

    1.1 什么是注解

    Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制
    Java 语言中的类、构造器、方法、成员变量、参数等都可以被注解进行标注
    在这里插入图片描述

    1.2 注解的作用

    对 Java 中类、方法、成员变量做标记,然后进行特殊处理,至于到底做何种处理由业务需求来决定
    例如:JUnit 框架中,标记了注解 @Test 的方法就可以被当成测试方法执行,而没有标记的就不能当成测试方法执行

    2.自定义注解

    2.1 注解格式

    自定义注解就是自己做一个注解来使用
    在这里插入图片描述

    特殊属性:
    value 属性:如果只有一个 value 属性的情况下,使用 value 属性的时候可以省略 value 名称不写
    但是如果由多个属性,且多个属性没有默认值,那么 value 名称是不能省略的

    2.2 代码实例

    首先写一个注解类 MyBook

    public @interface MyBook {
        String name();
    
        String[] authors();
    
        double price();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    再写一个测试类

    @MyBook(name = "《水浒传》", authors = {"施耐庵"}, price = 46.0)
    public class AnnotationDemo01 {
    
        @MyBook(name = "《三国演义》", authors = {"罗贯中"}, price = 36.0)
        private String name;
    
        @MyBook(name = "《西游记》", authors = {"吴承恩"}, price = 40.0)
        public AnnotationDemo01() {
        }
    
        @MyBook(name = "《红楼梦》", authors = {"曹雪芹"}, price = 46.0)
        public static void main(String[] args) {
            @MyBook(name = "《山海经》", authors = {"徐客"}, price = 43.6)
            int index = 1;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3.元注解

    3.1 常用元注解

    元注解:就是注解注解的注解
    常用元注解:
    @Target:约束自定义注解的标记范围
    @Retention:申明注解的生命周期

    3.2 @Target 常用值

    @Target 中可使用的值定义在 ElementType 枚举类中,常用如下

    说明
    CONSTRUCTOR构造器
    FIELD成员变量
    LOCAL_VARIABLE局部变量
    METHOD成员方法
    PARAMETER方法参数
    TYPE类、接口

    3.3 @Retention 常用值

    @Retention 中可使用的值定义在 RetentionPolicy 枚举类中,常用值如下:

    说明
    SOURCE注解将被编译器丢弃
    CLASS注解作用在源码阶段,字节码文件阶段,但不需要在运行时保留,默认值
    RUNTIME注解作用在源码阶段,字节码文件阶段,运行阶段(开发常用)

    4.注解解析

    4.1 注解解析相关接口

    注解的操作中经常需要进行解析,注解的解析就是判断是否存在注解,存在注解就解析出内容
    与注解解析相关的接口:
    Annotation:注解的顶级接口,注解都是 Annotation 类型的对象
    AnnotatedElement:该接口定义了与注解解析相关的解析方法

    方法说明
    Annotation[] getDeclaredAnnotations()获得当前对象上使用的所有注解,返回注解数组
    T getDeclaredAnnotation(Class annotationClass)根据注解类型获得对应注解对象
    boolean isAnnotationPresent(Class annotationClass)判断当前对象是否使用了指定的注解,如果使用了则返回 true,否则 false

    4.2 注解解析的技巧

    1. 注解在哪个成分上,我们就先拿哪个成分对象
    2. 比如注解作用成员方法,则要获取该成员方法对应的 Method 对象,再来拿上面的注解
    3. 比如注解作用再类上,则要该类的 Class 对象,再来拿上面的注解
    4. 比如注解作用在成员变量上,则要获得该成员变量对应的 Field 对象,再来拿上面的注解

    4.3 注解解析案例

    4.3.1 需求分析

    需求:

    1. 定义注解 Book,要求如下
      包含属性:String value() 书名
      包含属性:double price() 价格,默认值为 100
      包含属性:String[] authors() 作者
      限制注解使用的位置:类和成员方法上
      指定注解的有效范围:RUNTIME
    2. 定义 BookStore 类,在类和成员方法上使用 Book 注解
    3. 定义 AnnotationDemo 测试类获取 Book 注解上的数据

    4.3.2 代码实例

    首先创建 Book 注解

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.METHOD})
    public @interface Book {
        String value();
    
        double price() default 100;
    
        String[] authors();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    定义使用类 BookStore

    @Book(value = "《山海经》", price = 43.6, authors = {"徐客"})
    public class BookStore {
    
        @Book(value = "《西游记》", price = 40.0, authors = {"吴承恩"})
        public void getBook() {
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    定义测试类 AnnotationDemo

    import java.lang.reflect.Method;
    import java.util.Arrays;
    
    public class AnnotationDemo {
        public static void main(String[] args) {
            // 1.获取class对象
            Class c = BookStore.class;
            // 2.判断是否有Book注解
            if (c.isAnnotationPresent(Book.class)){
                Book book = (Book) c.getDeclaredAnnotation(Book.class);
                System.out.println("========================");
                System.out.print(book.value());
                System.out.print(book.price());
                System.out.println(Arrays.toString(book.authors()));
            }
            Method[] methods = c.getDeclaredMethods();
            for (Method method : methods) {
                Book book = (Book) method.getDeclaredAnnotation(Book.class);
                System.out.println("========================");
                System.out.print(book.value());
                System.out.print(book.price());
                System.out.println(Arrays.toString(book.authors()));
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    4.3.3 运行结果

    在这里插入图片描述

    5.模拟 JUnit 框架

    5.1 需求分析

    需求:定义若干个方法,只有加了 MyTest 注解,才可以在启动时被触发运行
    分析:

    1. 定义一个自定义注解 MyTest,只能注解方法,存活范围时一直都在
    2. 定义若干方法,只有用 @MyTest 注解标注的方法才能在启动时被触发运行

    5.2 代码实例

    首先定义 MyTest 注解类

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface MyTest {
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    然后创建方法类 AnnotationDemo

    public class AnnotationDemo {
    
        @MyTest
        public void method01(){
            System.out.println("运行方法method01");
        }
    
        @MyTest
        public void method02(){
            System.out.println("运行方法method02");
        }
    
        public void method03(){
            System.out.println("运行方法method03");
        }
    
        @MyTest
        public void method04(){
            System.out.println("运行方法method04");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    最后创建运行方法类 RunMethod

    import java.lang.reflect.Method;
    
    public class RunMethod {
        public static void main(String[] args) throws Exception {
            AnnotationDemo demo = new AnnotationDemo();
            // 1.获取class对象
            Class c = AnnotationDemo.class;
    
            // 2.获取所有方法
            Method[] methods = c.getDeclaredMethods();
    
            // 3.遍历
            for (Method method : methods) {
                // 4.判断是否有MyTest注解
                if (method.isAnnotationPresent(MyTest.class)){
                    method.invoke(demo);
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    5.3 运行结果

    在这里插入图片描述

  • 相关阅读:
    合宙Air724UG LuatOS-Air LVGL API控件-键盘 (Keyboard)
    rsync + inotify 同步数据
    leetcode 1488
    深入理解netty(二)Channel
    【Designing ML Systems】第 3 章 :数据工程基础
    机器学习-4
    Spring让读取和存储Bean更加简单(上篇)——使用注解储存Bean对象
    测试左移?测试右移?测试人员往哪移?
    【CSDN|每日一练】幼稚班作业
    Java基础知识
  • 原文地址:https://blog.csdn.net/qq_35132089/article/details/126990716