百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

什么是注解?为什么要使用注解?理解下annotation?

zhezhongyun 2024-12-03 06:31 62 浏览

推荐学习

一、什么是注解?

  从 JDK5 开始,Java增加对元数据的支持,也就是注解。简单理解就是代码里的特殊标志,这些标志可以在编译,类加载,运行时被读取,并执行相应的处理,以便于其他工具补充信息或者进行部署。

二、为什么要使用注解?

  注解可以被其他程序(比如:编译器等)读取,开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。

三、注解的相关概述

3.1 注解的格式

  注解就是以 @XXX 形式在代码中存在的,我们还可以为注解添加一些参数值,例如 @SuppressWarnings(value = "unchecked")

3.2 元注解

  元注解就是负责注解其它注解的注解。

  下图为Java定义的标准的 元注解类型,他们用来对其他的注解进行说明,可以在 Java API 的 java.lang.annotation 包中找到。

3.2.1 @Document

官方示例:

// since 1.5
@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Documented

官方描述:

  • 如果注释@Documented出现在注释类型A的声明中,那么元素上的任何@A注释都被认为是元素公共契约的一部分。
  • 更详细地说,当使用Documented对注释类型A进行注释时,类型A的注释的存在和值是A注释的元素的公共契约的一部分。相反,如果注释类型B没有被文档化注释,那么B注释的存在和值就不是B注释元素的公共契约的一部分。
  • 具体地说,如果注释类型是用Documented注释的,那么默认情况下,像javadoc这样的工具将在其输出中显示该类型的注释,而没有Documented的注释类型的注释将不会显示。

间而言之:

  如果使用了 @Documented ,就说明此类(或方法、字段等)的文档化注释就会被包含在JavaDoc中。

3.2.2 @Inherited

官方示例:

// since 1.5
@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Inherited

官方描述:

  • 指示自动继承批注类型。
  • 如果在注释类型声明上存在继承的元注释,并且用户在类声明上查询注释类型,而该类声明对此类型没有注释,则将自动在类的超类中查询注释类型。将重复此过程,直到找到此类型的注释,或到达类层次结构(对象)的顶部。
    如果没有超类具有此类型的注释,则查询将指示所讨论的类没有此类注释。
  • 请注意,如果注释类型用于注释类以外的任何内容,则此元注释类型无效。还要注意,这个元注释只会导致注释从超类继承;对实现接口的注释没有影响。

简而言之:

  子类可以继承父类(超类)中的该注解。这个注解指定被他修饰的注解将具有继承性——如果某个类使用了@XXX,则其子类将自动被@XXX修饰

代码示例:

 1 public class test2 {
 2 
 3     public static void main(String[] args) {
 4         Person person = new Person();
 5         Student student = new Student();
 6 
 7         Annotation[] parentAnnotation = person.getClass().getAnnotations();
 8         Annotation[] studentAnnotation = student.getClass().getAnnotations();
 9         for (Annotation annotation : parentAnnotation) {
10             System.out.println(annotation);
11         }
12         System.out.println("---------------------");
13         for (Annotation annotation : studentAnnotation) {
14             System.out.println(annotation);
15         }
16 
17         // 输出结果
18 //        @com.ruiyicloud.bbfbusiness.demo.annotation.MyAnnotation3()
19 //        ---------------------
20 //        @com.ruiyicloud.bbfbusiness.demo.annotation.MyAnnotation3()
21 
22     }
23 
24 
25 }
26 
27 @Target({ElementType.TYPE})
28 @Retention(RetentionPolicy.RUNTIME)
29 @Inherited
30 @interface MyAnnotation3{
31 
32 }
33 @MyAnnotation3
34 class Person{
35     String name;
36 }
37 
38 class Student extends Person{
39     int age;
40 }

注意:

  如果 MyAnnotation3 注解 去掉 @Inherited,则student.getClass().getAnnotations() 将输入空。

3.2.3 @Native

官方代码:

// since 1.8
@Documented
@Target(FIELD)
@Retention(SOURCE)
public @interface Native

官方描述:

  指示定义常量值的字段可以从本机代码引用。生成本机头文件的工具可以使用该注释作为提示,以确定是否需要头文件,如果需要,还应该包含哪些声明。

间而言之:

  使用本地方法,我们可以用java与底层系统的交互,如果使用Java获取不到我们想要的内容,我们可以选择使用本地方法。

  使用 @Native 注解修饰变量值的字段,则表示这个变量可以被本地代码引用。

代码示例:

  附上Integer的部分源码

 1 public final class Integer extends Number
 2         implements Comparable<Integer>, Constable, ConstantDesc {
 3     /**
 4      * A constant holding the minimum value an {@code int} can
 5      * have, -2<sup>31</sup>.
 6      */
 7     @Native public static final int   MIN_VALUE = 0x80000000;
 8 
 9 
10 
11   // 比较值的大小
12     public static int compareUnsigned(int x, int y) {
13         return compare(x + MIN_VALUE, y + MIN_VALUE);
14     }

3.2.4 @Repeatable

官方代码:

// since 1.8
@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Repeatable

官方描述:

  注释类型java.lang.annotation注释.Repeatable用于指示它(meta-)注释其声明的注释类型是可重复的。@Repeatable的值表示可重复注释类型的包含注释类型。

间而言之:

  使用@Repeatable这个声明的注解是可重复的。@Repeatable的值是另一个注解,其可以通过这个另一个注解的值来包含这个可重复的注解。

代码示例:

  FooContainer 作用于范围只能在注解类型上,所以作用于接口上时会报错

 1 import java.lang.annotation.ElementType;
 2 import java.lang.annotation.Repeatable;
 3 import java.lang.annotation.Target;
 4 
 5 public class test03 {
 6 
 7 }
 8 
 9 
10 @Target({ElementType.TYPE,ElementType.ANNOTATION_TYPE})
11 @Repeatable(FooContainer.class)
12 @interface Foo {}
13 
14 @Target(ElementType.ANNOTATION_TYPE)
15 @interface FooContainer {
16     Foo[] value();
17 }
18 
19 //正确的
20 @Foo @Foo
21 @interface FooContainer1 {
22     Foo[] value();
23 }
24 
25 // 错误的
26 @Foo @Foo
27 interface aa {
28     
29 }

注意事项:

  • Foo的保留时间至少与FooContainer一样长,其中保留用@Retention 注释显式或隐式表示。特别:
  • 如果Foo的保留为java.lang.annotation.RetentionPolicy.SOURCE,则FooContainer的保留为java.lang.annotation.RetentionPolicy.SOURCE。
  • 如果Foo的保留值为java.lang.annotation.RetentionPolicy.CLASS,则FooContainer的保留值为java.lang.annotation.RetentionPolicy.CLASS或 java.lang.annotation.RetentionPolicy.SOURCE。
  • 如果保留Foo是java.lang.annotation.RetentionPolicy.RUNTIME,则保留FooContainer是java.lang.annotation.RetentionPolicy.SOURCE, java.lang.annotation.RetentionPolicy.CLASS,或java.lang.annotation.RetentionPolicy.RUNTIME。

3.2.5 @Retention

官方示例:

// since 1.5
@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Retention

官方描述:

  • 指示带批注类型的批注要保留多长时间。如果批注类型声明上不存在保留批注,则保留策略默认为保留策略.CLASS.
  • 只有当元注释类型直接用于注释时,保留元注释才有效。如果元注释类型被用作另一个注释类型中的成员类型,则没有效果。

间而言之:

  此注解主要作用为在什么级别保存该注解信息,用于描述注解的声明周期,需要主要的是 SOURCE < CLASS < RUNTIME 。

3.2.6 @Target

官方示例:

// since 1.5
@Documented
@Retention(RUNTIME)
@Target(ANNOTATION_TYPE)
public @interface Target

官方描述:

  • 指示批注类型适用的上下文。JLS 9.6.4.1中指定了可应用注释类型的声明上下文和类型上下文,并在源代码中用java.lang.annotation注释.ElementType。
  • 如果@Target元注释不存在于注释类型T上,那么类型T的注释可以作为除类型参数声明之外的任何声明的修饰符来编写。
  • 如果存在@Target元注释,编译器将根据JLS 9.7.4强制执行由ElementType enum常量指示的使用限制。

简而言之:

  @Target注解主要用于描述注解的使用范围(例如,添加某些属性的时候注解可以使用在类上,添加某些属性的时候注解可以使用在方法上等)

3.3 注解的使用范围?

ElementType枚举常量

3.4 常用的几个注解

@Override :

  限定父类重写方法,当子类重写父类方法时,子类可以加上这个注解,可以确保子类确实重写了父类的方法,避免出现低级错误。

@FunctionalInterface:

  函数式接口,注解保证这个接口只有一个抽象方法,注意这个只能修饰接口。(函数式接口是指 接口中只有一个抽象方法(可以包含多个默认方法或多个static方法),接口体内只能声明常量字段和抽象方法,并且被隐式声明为public,static,final。接口里面不能有私有的方法或变量。)

@Deprecated:

  标示已过时,这个注解用于表示某个程序元素类,方法等已过时,当其他程序使用已过时的类,方法时编译器会给出警告。

@SuppressWarning:

  抑制编译器警告,被该注解修饰的元素以及该元素的所有子元素取消显示编译器警告。

四、自定义注解实战

  本例创建一个简单的注解,并在方法上、类上进行使用

@MyAnnotation
public class Main {
    @MyAnnotation
    public static void main(String[] args) {

    }
}

// Target 标识注解可以在什么地方使用
@Target({ElementType.METHOD,ElementType.TYPE})
// 标识此注解在什么地方还有效
@Retention(RetentionPolicy.RUNTIME)
// 标识是否将我们的注解生成在JavaDoc中
@Documented
// 子类可以继承父类的注解
@Inherited
@interface MyAnnotation{

}

五、总结

  总的来说,注解还是比较简单的。

作者: 学海无涯519

原文链接:https://www.cnblogs.com/wgx519/p/14373086.html

相关推荐

激光手术矫正视力对眼睛到底有没有伤害?

因为大家询问到很多关于“基质不能完全愈合”的问题,有必要在这里再详细解释一下。谢谢@珍惜年少时光提出的疑问:因为手头刚好在看组织学,其中提到:”角膜基质约占角膜的全厚度的90%,主要成分是胶原板层,...

OneCode核心概念解析——View(视图)

什么是视图?在前面的章节中介绍过,Page相关的概念,Page是用户交互的入口,具有Url唯一性。但Page还只是一个抽象的容器,而View则是一个具备了具体业务能力的特殊的Page,它可以是一个...

精品博文图文详解Xilinx ISE14.7 安装教程

在软件安装之前,得准备好软件安装包,可从Xilinx官网上下载:http://china.xilinx.com/support/download/index.html/content/xilinx/z...

卡片项目管理(Web)(卡片设计的流程)

简洁的HTML文档卡片管理,简单框架个人本地离线使用。将个人工具类的文档整理使用。优化方向:添加图片、瀑布式布局、颜色修改、毛玻璃效果等。<!DOCTYPEhtml><html...

GolangWeb框架Iris项目实战-JWT和中间件(Middleware)的使用EP07

前文再续,上一回我们完成了用户的登录逻辑,将之前用户管理模块中添加的用户账号进行账号和密码的校验,过程中使用图形验证码强制进行人机交互,防止账号的密码被暴力破解。本回我们需要为登录成功的用户生成Tok...

sitemap 网站地图是什么格式?有什么好处?

sitemap网站地图方便搜索引擎发现和爬取网页站点地图是一种xml文件,或者是txt,是将网站的所有网址列在这个文件中,为了方便搜索引擎发现并收录的。sitemap网站地图分两种:用于用户导...

如何在HarmonyOS NEXT中处理页面间的数据传递?

大家好,前两天的Mate70的发布,让人热血沸腾啊,不想错过,自学的小伙伴一起啊,今天分享的学习笔记是关于页面间数据伟递的问题,在HarmonyOSNEXT5.0中,页面间的数据传递可以有很多种...

从 Element UI 源码的构建流程来看前端 UI 库设计

作者:前端森林转发链接:https://mp.weixin.qq.com/s/ziDMLDJcvx07aM6xoEyWHQ引言由于业务需要,近期团队要搞一套自己的UI组件库,框架方面还是Vue。而业界...

jq+ajax+bootstrap改了一个动态分页的表格

最近在维护一个很古老的项目,里面是用jq的dataTable方法实现一个分页的表格,不过这些表格的分页是本地分页。现在想要的是点击分页去请求数据。经过多次的修改,以失败告终。分页的不准确,还会有这个错...

学习ES6- 入门Vue(大量源代码及笔记,带你起飞)

ES6学习网站:https://es6.ruanyifeng.com/箭头函数普通函数//普通函数this指向调用时所在的对象(可变)letfn=functionfn(a,b){...

青锋微服务架构之-Ant Design Pro 基本配置

青锋(msxy)-Gitee.com1、更换AntDesignPro的logo和名称需要修改文件所在位置:/config/defaultSetting.jsconstproSett...

大数据调度服务监控平台(大数据调度服务监控平台官网)

简介SmartKettle是针对上述企业的痛点,对kettle的使用做了一些包装、优化,使其在web端也能具备基础的kettle作业、转换的配置、调度、监控,能在很大一定程度上协助企业完成不同...

Flask博客实战 - 实现博客首页视图及样式

本套教程是一个Flask实战类教程,html/css/javascript等相关技术栈不会过多的去详细解释,那么就需要各位初学者尽可能的先去掌握这些基础知识,当然本套教程不需要你对其非常精通,但最起码...

Web自动化测试:模拟鼠标操作(ActionChains)

在日常的测试中,经常会遇到需要鼠标去操作的一些事情,比如说悬浮菜单、拖动验证码等,这一节我们来学习如何使用webdriver模拟鼠标的操作首页模拟鼠标的操作要首先引入ActionChains的包fro...

DCS F-16C 中文指南 16.9ILS仪表降落系统教程

10–ILS教程我们的ILS(仪表着陆进近)将到达Batumi巴统机场。ILS频率:110.30跑道航向:120磁航向/126真航向无线电塔频率:131.0001.设置雷达高度表开关打开(前)并...