首页 > 其他 > 详细

自定义注解与解析注解

时间:2020-06-18 10:05:13      阅读:59      评论:0      收藏:0      [点我收藏+]

1 注解的概述

1.1 注解的概念

  • 注解是JDK1.5的新特性。

  • 注解相当一种标记,是类的组成部分,可以给类携带一些额外的信息。

  • 标记(注解)可以加在包,类,字段,方法,方法参数以及局部变量上。

  • 注解是给编译器或JVM看的,编译器或JVM可以根据注解来完成对应的功能。

    注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,以后,javac编译器、开发工具和其他程序可以通过反射来了解你的类及各种元素上有无何种 标记,看你的程序有什么标记,就去干相应的事,标记可以加在包、类,属性、方法,方法的参数以及局部变量上。

引用数据类型:类,接口,数组,枚举,注解

1.2 注解的作用

注解的作用就是给程序带入参数。

以下几个常用操作中都使用到了注解:

  1. 生成帮助文档@author和@version

    • @author:用来标识作者姓名。

    • @version:用于标识对象的版本号,适用范围:文件、类、方法。

      • 使用@author和@version注解就是告诉Javadoc工具在生成帮助文档时把作者姓名和版本号也标记在文档中。如下图:

        技术分享图片

        IDEA中生成文档的方式:

        技术分享图片

  2. 编译检查@Override

    • @Override:用来修饰方法声明。

      • 用来告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败。如下图

      技术分享图片

  3. **框架的配置( 框架 = 代码 + 配置 ) **

    • 具体使用请关注框架课程的内容的学习。

1.3 常见注解

  1. @author:用来标识作者名,eclipse开发工具默认的是系统用户名。
  2. @version:用于标识对象的版本号,适用范围:文件、类、方法。
  3. @Override :用来修饰方法声明,告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败。
  4. @Override
  5. @FunctionnalInterface
  6. @Test
  7. @After
  8. @Before

2 自定义注解

2.2.1 定义格式

public @interface 注解名{

}

如:定义一个名为Student的注解
public @interface Student {

} 

注解本质上就是一个接口。所有注解都会继承一个接口:Annotation

技术分享图片

2.2 注解的属性

  1. 属性的格式

    • 格式1:数据类型 属性名();
    • 格式2:数据类型 属性名() default 默认值;
  2. 属性定义示例

    // 姓名
    String name();
    // 年龄
    int age() default 18;
    // 爱好
    String[] hobby();
    
  3. 属性适用的数据类型

    * 八种数据数据类型(int,short,long,double,byte,char,boolean,float)
    * String,Class,注解类型,枚举类
    * 以上类型的数组形式
    

3 使用自定义注解

3.1 定义和注解

  1. 定义一个注解:Book
    • 包含属性:String value() 书名
    • 包含属性:double price() 价格,默认值为 100
    • 包含属性:String[] authors() 多位作者
  2. 代码实现
public @interface Book {
    String value();
    double price() default 100;
    String[] authros();
}

3.2 使用注解

  1. 定义类在成员方法上使用Book注解
public class AnnotationDemo01 {
    @Book(value = "JavaEE开发详解",authros = {"黑马程序员","传智学院"})
    public void show(){
        
    }
}
  1. 使用注意事项
    • 如果属性有默认值,则使用注解的时候,这个属性可以不用赋值。
    • 如果属性没有默认值,那么在使用注解时一定要给属性赋值。

3.3 特殊属性value

如果注解中只有一个属性且名字叫value,则在使用该注解时可以直接给该属性赋值,而不需要给出属性名。
如果注解中除了value属性之外还有其他属性且只要有一个属性没有默认值,则在给属性赋值时value属性名也不能省略了。

因此,如果注解中只有一个属性时,一般都会将该属性名命名为value

public class Demo01 {

    @C("ccc")//如果有其他的属性,并且都含有default,都使用默认值的情况下,只给value赋值的情况下也可以省略value=
    @B(value = "bb", age = 18)//如果出了value还有其他的属性而且没有default数据,不能省略value=
    @A("aa") //如果只有value属性,赋值时,可以省略 value=
    public void test1() {

    }

}

@interface A {
    String value();
}

@interface B {
    String value();

    int age();
}

@interface C {
    String value();

    int age() default 18;
}

4 注解之元注解

4.1元注解概述

? Java官方提供的注解 用来定义注解的注解 任何官方提供的非元注解的定义都使用到了元注解。

元注解的作用:用来限定其他注解的生命周期,限定可以使用的地方。

4.2 常用的元注解

@Target

作用:用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位置。

可使用的值定义在ElementType枚举类中,常用值如下
  TYPE,类,接口
  FIELD, 成员变量
  METHOD, 成员方法
  PARAMETER, 方法参数
  CONSTRUCTOR, 构造方法
  LOCAL_VARIABLE, 局部变量

@Retention

作用:用来标识注解的生命周期(有效范围)

可使用的值定义在RetentionPolicy枚举类中,常用值如下
  SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
  CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,【默认值】
  RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段

【代码示例】

示例中为JDK定义的@override注解

技术分享图片

5 注解解析

什么是注解解析? 使用Java技术获得注解上数据的过程则称为注解解析。

与注解解析相关的接口

Annotation: 注解类的父类型,该类是所有注解的父接口。
AnnotatedElement:该接口定义了与注解解析相关的方法
    1. T getAnnotation(Class<T> annotationClass) 
   				根据注解类型获得对应注解对象
   
    2. Annotation[]	getAnnotations()
       		获得当前对象上使用的所有注解,返回注解数组,包含父类继承的
   
    3. Annotation[]	getDeclaredAnnotations()
       		得当前对象上使用的所有注解,返回注解数组,只包含本类的
   
    4. boolean	isAnnotationPresent(Class<Annotation> annotationClass)
       		判断当前对象是否使用了指定的注解,如果使用了则返回true,否则false

获取注解数据的原理

Field,Method,Constructor,Class等类都是实现了AnnotatedElement接口

注解作用在哪个成员上就会得该成员对应的对象来获得注解
  比如注解作用成员方法,则要获得该成员方法对应的Method对象
  比如注解作用在类上,则要该类的Class对象
  比如注解作用在成员变量上,则要获得该成员变量对应的Field对象。

5.1 需求说明

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

5.2 代码实现

自定义注解

//自定义注解
@Target({ElementType.METHOD,ElementType.TYPE}) //作用在方法和类上
@Retention(RetentionPolicy.RUNTIME) //在运行时候有效
@interface Bookshelf{
    //属性
    String name();
    double price() default 9.9;
    String[] authors();
}


注册到Book实体类

@Bookshelf(name = "红楼梦",price = 99.9,authors = {"曹雪芹","AAA"})
public class Book {

    @Bookshelf(name = "西游记",authors = {"吴承恩","BBB"})
    public void show(){}
}

测试类解析

package com.homework_test.test02;

import java.lang.reflect.Method;
import java.util.Arrays;

public class Test {
    public static void main(String[] args)throws Exception {
        //创建Book类的字节码对象(获取类上的注解)
        Class<Book> bookClass = Book.class;


        //判断该class对象是否使用了该 注解
        if(bookClass.isAnnotationPresent(Bookshelf.class)){
            //获得该注解类型的对象
            Bookshelf bookshelf = bookClass.getAnnotation(Bookshelf.class);

            String name = bookshelf.name();
            System.out.println("name = " + name);//name = 红楼梦
            String[] authors = bookshelf.authors();
            System.out.println("authors = " + Arrays.toString(authors));//authors = [曹雪芹, AAA]
            double price = bookshelf.price();
            System.out.println("price = " + price);//price = 9.9
        }

        System.out.println("************************************");
        //解析方法上的注解
        //1.通过class对象获取指定方法对象
        Method showMethod = bookClass.getMethod("show");
        //2.开始解析注解
        if(showMethod.isAnnotationPresent(Bookshelf.class)){
            //获取注解对象
            Bookshelf bookshelf = showMethod.getAnnotation(Bookshelf.class);

            String name = bookshelf.name();
            System.out.println("name = " + name);//name = 西游记
            double price = bookshelf.price();
            System.out.println("price = " + price);//price = 99.9
            String[] authors = bookshelf.authors();
            System.out.println("authors = " + Arrays.toString(authors));//authors = [吴承恩, BBB]


        }
    }
}


自定义注解与解析注解

原文:https://www.cnblogs.com/liqiliang1437/p/13155692.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!