用了这么多年的注解,你知道注解是干嘛的嘛?

JAVA葵花宝典

共 5228字,需浏览 11分钟

 ·

2020-07-28 16:02


正文

引言:

最近入职了新公司,前期比较忙,公司的项目用到了很多自定义注解,自定义注解由于是公司架构设计的,所以和同事沟通中发现很多小伙伴对注解一知半解,晚上在公司加了会班,发布这篇关于注解的文章,希望有帮助到你


什么是注解?


注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、 接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。

注解的作用

注解可以用来说明程序,给计算机解释,并非给开发人员看的,注解也可以用来被其他程序读取

注解的格式

注解格式为"@注解名称",在代码中存在,可以添加一些参数,如下:

1@SpringBootApplication
2public class SpringBootAdminClientApplication {
3    public static void main(String[] args) {
4        SpringApplication.run(SpringBootAdminClientApplication.class, args);
5    }
6}
  • Annotnation在哪里使用?

可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,可以通过反射机制编程实现对这些元数据的访问

  • 作用分类:

编写文档:通过代码里标识的注解生成文档【生成文档doc文档】

代码分析:通过代码里标识的注解对代码进行分析【使用反射】

编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】

  • 常见注解:

  • @author:用来标识作者名,eclipse开发工具默认的是系统用户名。

  • @since:  从那个版本开始

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

  • @Override:用来修饰方法声明,告诉编译器该方法是重写父类中的方法,如果父类不存在该方法,则编译失败。

自定义注解

自定义注解: 注解本质上就是一个接口,该接口默认继承Annotation接口

1public interface MyAnno extends java.lang.annotation.Annotation {}
  • 自定义注解

1// 空注解
2public @interface Mobai{
3}
  • 含参数的注解

只能使用Java提供的基本数据类型,String可以,Class可以,枚举类,其他暂未测试,包装类不可以.自定义类不可以

 1public @interface Anno02 {
2    // 属性
3    String name();
4    double price() default 99;
5    String[] authors();
6
7//    Anno01 abc(); // 注解
8//    WeekDay w();
9//    Class p();
10}
11enum WeekDay {
12    SUN, MON
13}
14class Person {
15}
注解的属性类型以及使用自定义注解

只能包含八种基本数据类型,String可以,注解,枚举,Class,或者以上类型的一堆数组,自定义类不可以

  • 注解可以用来保存数据

  • 使用自定义注解格式:

@注解名(属性名=属性值, 属性名=属性值)

需要注意的是:注解的属性可以有默认值,当使用注解时不赋值就使用默认值,赋值就按照赋的值

  • 定义注解

1public @interface MoBai {
2    // 名字
3    String name();
4
5    // 默认属性
6    String value() default "框架师";
7}
  • 使用注解

 1public class AnnactionTest {
2
3    @MoBai(name = "墨白",value = "")
4    public static void main(String[] args) {
5    }
6
7    @Test
8    public void annTest(){
9    }
10}
自定义注解的特殊情况

当注解只有一个属性,并且属性名是value时,在使用注解时可以省略属性名

  • 自定义注解

1public @interface MoBai {
2    String value();
3}
  • 使用注解

1@MoBai("abc")
2public class Demo11 {
3    @MoBai(value = "abc")
4    public static void main(String[] args) {
5    }
6}
元注解

@Target

@Retention

什么是元注解:修饰注解的注解叫做元注解

@Target注解

这个注解默认情况下可以放在任意位置,也可以限制注解放在那些位置

@Target(ElementType.TYPE)           注解只能放在类或者接口上

@Target(ElementType.CONSTRUCTOR)    注解只能放在构造方法上

@Target(ElementType.FIELD)          注解只能放在成员变量上

@Target(ElementType.METHOD)         注解只能放在成员方法上

@Target(ElementType.LOCAL_VARIABLE) 注解只能放在局部变量上

具体可以看一下源码,源码解释的比较详细

@Retention

这个注解默认是存在Class阶段,并且限制了注解存活时间;如下

SOURCE = = = = = = = = = = >>CLASS = = = = = = = = = = = = = >>RUNTIME

源代码阶段(.java) = = = = >>编译 = = = >>.class = = = = = = >>运行

  • 自定义注解

1//@Target(ElementType.TYPE) // 注解只能放在类或者接口上
2//@Target(ElementType.CONSTRUCTOR) // 注解只能放在构造方法上
3//@Target(ElementType.FIELD) // 注解只能放在成员变量上
4//@Target(ElementType.METHOD) // 注解只能放在成员方法上
5//@Target(ElementType.LOCAL_VARIABLE) // 注解只能放在局部变量上
6@Retention(RetentionPolicy.RUNTIME)
7public @interface MoBai {
8}
  • 使用注解

 1@MoBai
2public class Demo12 {
3    @MoBai
4    private String a;
5
6    @MoBai
7    public Demo12() {
8
9    }
10
11    @MoBai
12    public static void main(String[] args) {
13        @MoBai
14        int x = 10;
15    }
16}
注解的解析
  • 什么是注解解析

  • 获取注解中保存的数据

  • 注解解析相关接口

1AnnotatedElement接口中:
2Annotation getAnnotation(Class annotationClass) 获取一个注解**
3Annotation[] getAnnotations()  获取多个注解
4boolean isAnnotationPresent(Class annotationClass) 判断有没有指定的注解

注意: Constructor , Field , Method实现了AnnotatedElement接口

如何解析注解
  • 注解在谁头上,就用谁来获取注解

  • 注解在构造方法上,使用Constructor对象获取注解

  • 注解在成员方法上,使用Method对象获取注解

  • 注解在成员变量上,使用Field对象获取注解

  • 使用反射

  • 创建自定义注解

 1import java.lang.annotation.ElementType;
2import java.lang.annotation.Retention;
3import java.lang.annotation.RetentionPolicy;
4import java.lang.annotation.Target;
5/**
6 * Software:IntelliJ IDEA 2020.1 x64
7 * Author: MoBai·杰
8 * [@]Interface:MoBook
9 * 注解描述: 自定义注解
10 */

11// 限定方法使用
12@Target(ElementType.METHOD)
13// 活到运行时候
14@Retention(RetentionPolicy.RUNTIME)
15public @interface MoBook {
16    String name();
17
18    double price();
19
20    String[] authors();
21}
  • 定义数据类使用注解

 1/**
2 * Software:IntelliJ IDEA 2020.1 x64
3 * Author: MoBai·杰
4 * ClassName:Book
5 * 类描述: 书籍类
6 */

7public class Book {
8    @MoBook(name = "框架师", price = 25.0, authors = "墨白")
9    public void sell() {
10
11    }
12}
  • 测试类

 1public class TestMoBook {
2    public static void main(String[] args) throws Exception {
3        // 1.获取Class对象
4        Class className = Class.forName("com.mobai.annion.Book");
5        // 2.获取Method对象
6        Method method = className.getMethod("sell");
7        // 3.通过method对象获取注解
8        Annotation[] annotations = method.getAnnotations();
9        // 4.遍历数组
10        for (Annotation annotation : annotations) {
11            System.out.println("annotation = " + annotation);
12        }
13        // 3.3 boolean isAnnotationPresent(Class annotationClass)
14        //  判断有没有指定的注解
15        boolean b = method.isAnnotationPresent(MoBook.class);
16        System.out.println(b);
17        if (b) {
18            // 3.2 Annotation getAnnotation(Class annotationClass) 获取一个注解
19            MoBook ann = method.getAnnotation(MoBook.class);
20            System.out.println(ann.name() + "::" + ann.price() + "::" + Arrays.toString(ann.authors()));
21        }
22    }
23}


推荐阅读:

推荐 33 个 IDEA 最牛配置,好用到飞起来!
阿里巴巴的独立环境是如何实现的
2020 年 7 月编程语言排行榜
Java如何优雅地实现单元测试与集成测试

坚持是一种信仰,在看是一种态度!

浏览 7
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报