写在前面

现在的java主流框架中,注解无处不在,因此我们完全有必要搞明白注解到底是什么。如何理解注解,它到底是怎么起作用的。

注解的定义

java是这样定义注解的:Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。什么又是元数据的呢?说白了就是描述数据的数据,既然注解被称为元数据,具有描述作用,那么我们是不是可以把注解理解成标签来使用呢。我觉得学习注解,应该着重理解注解的作用是什么?在日常工作中是如何使用的即可,一般无需我们定义和解释注解,而注解解释器,也就是读取注解的类在框架中多数是隐藏起来的,除非阅读源码,否则根本看不到。

日常开发中新建Java类,我们使用class、interface比较多,而注解和它们一样,也是一种类的类型,他是用的修饰符为 @interface

格式

public @interface 注解名称{

属性列表;

}

分类

注解可分为JDK内置注解和自定义注解

内置的注解:

Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

作用在代码的注解是

@Override - 检查该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。

@Deprecated - 标记过时方法。如果使用该方法,会报编译警告。

@SuppressWarnings - 指示编译器去忽略注解中声明的警告。

作用在其他注解的注解(或者说 元注解)是:

@Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。

@Documented - 标记这些注解是否包含在用户文档中。

@Target - 标记这个注解应该是哪种 Java 成员。

@Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

从 Java 7 开始,额外添加了 3 个注解:

@SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。

@FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。

@Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

自定义注解:

自定义注解就是自己编写的注解,而框架中所写的那些注解也可称为自定义注解,也是通过被元注解标记而写出来的注解。

注解的作用

如果说注释是写给人看的,那么注解就是写给程序看的。它更像一个标签,贴在一个类、一个方法或者字段上。它的目的是为当前读取该注解的程序提供判断依据。

要牢记,只要用到注解,必然存在三角关系:定义注解,使用注解,注解解析。如下图:

往往我们要做的是使用注解,而注解的定义跟解析一般框架都帮我们做好了。

注解的使用

1.自定义注解怎么写?

在编写自定义注解之前,我们必须先了解元注解

以下部分摘自简书(若 | 寒),对元注解的解析做的非常不错。

上面定义中提到,元注解可以理解为注解的注解,它是作用在注解中,方便我们使用注解实现想要的功能。元注解分别有@Retention、 @Target、 @Document、 @Inherited和@Repeatable(JDK1.8加入)五种。

@Retention

Retention英文意思有保留、保持的意思,它表示注解存在阶段是保留在源码(编译期),字节码(类加载)或者运行期(JVM中运行)。在@Retention注解中使用枚举RetentionPolicy来表示注解保留时期

@Retention(RetentionPolicy.SOURCE),注解仅存在于源码中,在class字节码文件中不包含

@Retention(RetentionPolicy.CLASS), 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得

@Retention(RetentionPolicy.RUNTIME), 注解会在class字节码文件中存在,jvm虚拟机在加载class文件后仍然存在,在运行时可以通过反射获取到

如果我们是自定义注解,则通过前面分析,我们自定义注解如果只存着源码中或者字节码文件中就无法发挥作用,而在运行期间能获取到注解才能实现我们目的,所以自定义注解中肯定是使用 @Retention(RetentionPolicy.RUNTIME)

@Target

Target的英文意思是目标,这也很容易理解,使用@Target元注解表示我们的注解作用的范围就比较具体了,可以是类,方法,方法参数变量等,同样也是通过枚举类ElementType表达作用类型

@Target(ElementType.TYPE) 作用接口、类、枚举、注解

@Target(ElementType.FIELD) 作用属性字段、枚举的常量

@Target(ElementType.METHOD) 作用方法

@Target(ElementType.PARAMETER) 作用方法参数

@Target(ElementType.CONSTRUCTOR) 作用构造函数

@Target(ElementType.LOCAL_VARIABLE)作用局部变量

@Target(ElementType.ANNOTATION_TYPE)作用于注解(@Retention注解中就使用该属性)

@Target(ElementType.PACKAGE) 作用于包

@Target(ElementType.TYPE_PARAMETER) 作用于类型泛型,即泛型方法、泛型类、泛型接口 (jdk1.8加入)

@Target(ElementType.TYPE_USE) 类型使用.可以用于标注任意类型除了 class (jdk1.8加入)

一般比较常用的是ElementType.TYPE类型

@Documented

Document的英文意思是文档。它的作用是能够将注解中的元素包含到 Javadoc 中去。

@Inherited

Inherited的英文意思是继承,但是这个继承和我们平时理解的继承大同小异,一个被@Inherited注解了的注解修饰了一个父类,如果他的子类没有被其他注解修饰,则它的子类也继承了父类的注解。

@Repeatable

Repeatable的英文意思是可重复的。顾名思义说明被这个元注解修饰的注解可以同时作用一个对象多次,但是每次作用注解又可以代表不同的含义。

注解属性类型

注解属性类型可以有以下列出的类型

基本数据类型

String

枚举类型

注解类型

Class类型

以上类型的一维数组类型

2.如何解析使用注解?

前面说到了注解如何定义,在哪使用等,其他注解的关键,是获取注解中的属性值,这才是使用注解的真正目的。前面也说到,要想使用自定义的注解,必须要使用@Retention(RetentionPolicy.RUNTIME), 注解会在class字节码文件中存在,jvm虚拟机在加载class文件后仍然存在,在运行时可以通过反射获取到,而获取注解的主要手段就是通过反射来获取。其中有三个主要的方法

/**是否存在对应 Annotation 对象*/

public boolean isAnnotationPresent(Class extends Annotation> annotationClass) {

return GenericDeclaration.super.isAnnotationPresent(annotationClass);

}

/**获取 Annotation 对象*/

public A getAnnotation(Class annotationClass) {

Objects.requireNonNull(annotationClass);

return (A) annotationData().annotations.get(annotationClass);

}

/**获取所有 Annotation 对象数组*/

public Annotation[] getAnnotations() {

return AnnotationParser.toArray(annotationData().annotations);

}

一个小demo:

MyAnnotation.java

@Target({ElementType.TYPE,ElementType.METHOD})

@Documented

@Retention(RetentionPolicy.RUNTIME)

public @interface MyAnnotation {

String value() default "apang";

int num() default 99;

}

TestAnnotation.java

@MyAnnotation(value = "注解用在类上")

public class TestAnnotation {

@MyAnnotation()

public void test1() {

//使用默认值

}

@MyAnnotation(value = "注解用在方法上",num = 88)

public void test2() {

//使用自定义值

}

}

MyAnnotationProcessor.java

public class MyAnnotationProcessor {

public static void main(String[] args) throws Exception {

//获取类对象

Class clazz1 = TestAnnotation.class;

MyAnnotation annotation = TestAnnotation.class.getAnnotation(MyAnnotation.class);

System.out.println(annotation);

System.out.println(annotation.value());

System.out.println(annotation.num());

Method[] methods = clazz1.getDeclaredMethods();

for (Method m : methods) {

Annotation an = m.getAnnotation(MyAnnotation.class);

System.out.println(an);

System.out.println(((MyAnnotation) an).value());

System.out.println(((MyAnnotation) an).num());

}

}

}

输出

>>> @com.apang.annotation.MyAnnotation(value=注解用在类上, num=99)

>>> 注解用在类上

>>> 99

>>> @com.apang.annotation.MyAnnotation(value=注解用在方法上, num=88)

>>> 注解用在方法上

>>> 88

>>> @com.apang.annotation.MyAnnotation(value=apang, num=99)

>>> apang

>>> 99

java注解怎么写_java注解相关推荐

  1. java中qualifier注解怎么写_Java 注解 Qualifier

    有如下接口: public interfaceEmployeeService {publicEmployeeDto getEmployeeById(Long id); } 同时有下述两个实现类 Emp ...

  2. java注解详解_Java注解详解

    Annotation是从JDK5.0开始引入的新技术. Annotation的作用:–不是程序本身,可以对程序作出解释.(这一点,跟注释没什么区别)–可以被其他程序(比如:编译器等)读取.(注解信息处 ...

  3. java 注解与反射_Java注解与反射直接上手

    什么是注解(Annotation) 注解顾名思义为注释.讲解,可以理解为一种标签或标记,可以用在类.方法或者域上.向类.方法等添加注解,相当于给他们贴上了一层标签. 注解使用 在使用注解时,在类名.方 ...

  4. java注解的反射_Java注解与反射

    概要 本文主要是总结Java注解与反射的相关知识,加深自己对Java类动态语言的理解,同时为日后学习Spring打下基础. 注解: 什么是注解 Annotation的作用 不是程序本身,但是可以对程序 ...

  5. java注解使用变量_java注解的使用

    java中注解的使用 1.说再前面 使用注解开发的好处 1.使代码更加干净易读,易于维护修改.比如,以前使用spring的开发,都是基于xml文件实现了统一的配置管理,但是缺点也是显而易见的,就是随着 ...

  6. java中如何写一个注解

    1注解有什么用?   注解的作用基本有三个:       1.生成文档.这是最常见的,也是java 最早提供的注解.常用的有 @see @param @return 等       2. 跟踪代码依赖 ...

  7. java annotation详解_Java注解Annotation详解

    从JDK5开始,Java增加了Annotation(注解),Annotation是代码里的特殊标记,这些标记可以在编译.类加载.运行时被读取,并执行相应的处理.通过使用Annotation,开发人员可 ...

  8. java 注解报错_java注解验证接收参数 返回注解字段的错误

    1.在controller接口方法接收参数加上 @Valid注解 并且在实体类参数后紧跟 BindingResult bindingresul BindingResultMsgUtil工具类: pub ...

  9. java程序怎么写_java程序怎么写

    java程序怎么写? 一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作.下面简要介绍下类.对象.方法和实例变量的概念. 推荐教程:<java学习> 对象: ...

最新文章

  1. java中对Excel的创建、样式修改
  2. Java之相对路径找不到文件问题解决方法
  3. Windows系统安装改磁盘格式
  4. 计算机网络·物理层练习题
  5. POJ3265 Problem Solving ——动态规划——Pku3265
  6. FirstBird--项目流程
  7. Redis缓存雪崩、缓存穿透、热点Key
  8. 【LeetCode】44. Wildcard Matching (2 solutions)
  9. 【LeetCode】剑指 Offer 67. 把字符串转换成整数
  10. 力扣 两两交换链表中的节点
  11. 2952 细胞分裂 2
  12. sklearn学习笔记之开始
  13. 基于springboot小区物业管理系统
  14. 不同形式弧微分的求解
  15. mysqldump参数之-A -B
  16. php源码后台密码被改了,帝国cms后台密码重置插件后台密码恢复找回密码工具
  17. Java Web基础
  18. Java jdt 编辑_JDT:打开Java编辑器并显示特定成员
  19. 用c语言实现简单的项目信息管理系统(单向链表实现)
  20. [翻译] 数学翻译词汇

热门文章

  1. 10倍效率提升的低代码IDE
  2. 虎年姓氏头像微信小程序源码+AI智能配音小程序源码+喝酒娱乐多功能小程序源码
  3. java apply_apply()与call()的区别
  4. 刺激消费的线上盲盒运营解析,你知道盲盒吗
  5. 模型的量化转换是什么
  6. pdfjs 插件进行 自定义 遮罩 打印
  7. C++ 中auto与auto的区别 (详细)
  8. 11:Polly-缓存(Cache)
  9. Typora文件别人打开不显示图片-图像处理
  10. MTU其实可以分成二层MTU和三层MTU