用了这么多年的注解,你知道注解是干嘛的嘛?
引言:
最近入职了新公司,前期比较忙,公司的项目用到了很多自定义注解,自定义注解由于是公司架构设计的,所以和同事沟通中发现很多小伙伴对注解一知半解,晚上在公司加了会班,发布这篇关于注解的文章,希望有帮助到你
注解(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(ElementType.TYPE) 注解只能放在类或者接口上
@Target(ElementType.CONSTRUCTOR) 注解只能放在构造方法上
@Target(ElementType.FIELD) 注解只能放在成员变量上
@Target(ElementType.METHOD) 注解只能放在成员方法上
@Target(ElementType.LOCAL_VARIABLE) 注解只能放在局部变量上
具体可以看一下源码,源码解释的比较详细
这个注解默认是存在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如何优雅地实现单元测试与集成测试