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

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

myzbx 2024-12-03 16:40 62 浏览

推荐学习

  • 牛掰!“基础-中级-高级”Java程序员面试集结,看完献出我的膝盖

  • 真真香!耗时大半个月收整全套「Java架构进阶pdf」没白费

一、什么是注解?

  从 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{

}

五、总结

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

相关推荐

砌体植筋拉拔试验检验值到底是6.0KN,还是10.2KN,如何计算确定

砌体拉结筋植筋养护完成后,需对所植钢筋进行拉拔试验,以检验植筋的锚固强度是否满足设计要求。检测时,按照一定的抽样比例进行拉拔试验。根据《混凝土结构后锚固技术规程》JGJ145-2013,以同品种、同...

柴油机功率如何计算?计算柴油机功率需要哪些参数?

在汽车领域,对于柴油机功率的计算是一项重要的工作,它有助于我们更好地了解柴油机的性能和适用场景。下面我们就来详细探讨一下柴油机功率的计算方法以及所需的参数。首先,我们要了解计算柴油机功率常用的公式。在...

变压器短路阻抗的作用和计算方法(变压器短路阻抗的作用和计算方法是什么)

变压器短路阻抗的作用和计算方法短路阻抗是在负载试验中测量的一项数据,它是二次侧短接并流过额定电流时,一次侧施加的电压与额定电压的的百分数。那么测量变压器的短路阻抗有什么意义呢?其实变压器的阻抗电压乃是...

9.35m层高高支模支撑架计算书(支模架多高属于高支模)

某工厂新扩建的建筑面积为1989.2m^2,建筑物总体分为2层,但局部为4层。建筑物檐高19.4m,建筑物总高23m。建筑物呈长方形设置,长度为48.20m,宽度为23.88m,结构形式为框架结构...

吊篮(悬挂装置前梁加长)安全复核计算书

吊篮(悬挂装置前梁加长)安全复核计算书一种超常规搭设的高处作业吊篮,因使用要求将吊篮悬挂装置前梁加长设置,本计算书针对这种工况的校核,以作参考。计算依据:1、《高处作业吊篮》GB/T19155-...

电功率计算公式精编汇总(电功率计算视频讲解)

一、电功率计算公式:1在纯直流电路中:P=UIP=I2RP=U2/R式中:P---电功率(W),U---电压(V),I----电流(A),R---电阻(Ω)。2在单相交流电路中:P=UIcosφ...

灌注桩承载力检测方法及步骤(灌注桩承载力不够怎么办)

检测灌注桩的承载力是确保基础工程安全可靠的关键环节,检测结果的精细能准确为我们提供可靠的数据,让我们能准确判断桩基础的承载力,方便后续施工安排,同样也能让我们根据数据分辨出有问题桩基,采取可靠有效的措...

很哇塞的体积计算方法:向量叉乘 很哇塞的体积计算方法

高中数学必看:向量叉乘,体积的神。大家都知道a、b的向量是什么意思,但是a、b的向量又是什么?很多同学都不知道,向量的向量在高中阶段非常有用,虽然它是大学的知识,在高中阶段可以干两件事。·第一件事,表...

施工升降机基础(设置在地库顶板回顶)计算书

施工升降机基础(设置在地库顶板回顶)计算书计算依据:1、《施工现场设施安全设计计算手册》谢建民编著2、《建筑地基基础设计规范》GB50007-20113、《混凝土结构设计标准》GB/T50010-2...

剪力墙水平钢筋根数如何计算?(剪力墙水平钢筋绑扎搭接规范)

剪力墙水平钢筋根数的计算需综合考虑墙高、起步距离、间距及构造要求等因素,具体步骤如下及依据:1.基本计算公式水平钢筋根数计算公式为:根数=(墙高-起步距离)/间距(墙高-起步距离)/间距...

直流电路常用计算公式(直流电路常用计算公式有哪些)

1、电阻导体阻碍电流通过的能力叫做电阻,用字母R表示,单位欧(Ω)。R=ρl/s式中R-导体的电阻,欧(Ω);ρ-导体的电阻率,欧·米(Ω·m);l-导体的长度,米(m);s-导体的截面积,平方米(m...

电气主电路图的绘制特点(电气原理图主电路)

1、电气主电路图中的电气设备、元件,如电源进线、变压器、隔离开关、断路器、熔断器、避雷器等都垂直绘制,而母线则水平绘制。电气主电路图除特殊情况外,几乎无一例外地画成单线图,并以母线为核心将各个项目(如...

中考总复习:物理专题 功和机械能 (功的计算、功率、动能、势能)

中考物理专题:功与机械能解析一、力学中的功——能量转化的桥梁功是力对物体能量变化的量度,需满足两要素:作用在物体上的力、物体沿力方向移动距离。例如推箱子时,若箱子未移动,推力不做功;若箱子滑动,推力做...

40亿QQ号,不超过1G内存,如何去重?

分享一道网上很火的面试题:40亿QQ号,不超过1G的内存,如何去重?这是一个非常经典的海量数据去重问题,并且做了内存限制,最多只能1GB,本文跟大家探讨一下~~一、常规思路我们日常开发中,如果谈到去重...

填充墙体拉结筋植筋深度、孔径、拉拔试验承载力计算!

今天分享下植筋间距及保护层要求:根据JGJ145-2013混凝土后锚固技术规程要求植筋与混凝土结构边缘不应小于5mm,植筋为两根及以上时水平间距为不应小于5d(d为钢筋直径)。根据混凝土结构后锚固技...