Java注解总结(史上最全,有这一篇就够了)

我的视频课:《Java注解精讲》欢迎大家围观~

什么是注解?

注解的定义

官网描述如下:

Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。Java 注解是从 Java5 开始添加到 Java 的。

将上面的话再翻译一下,如下:
(1)元数据在开发中的作用就是做数据约束和标准定义,可以将其理解成代码的规范标准(代码的模板);
(2)代码的模板(元数据)不直接影响代码的执行,它只是帮助我们来更快捷的开发;

综上,注解是一种元数据,可以将它理解为注释、解释,它为我们在代码中添加信息提供了一种形式化的方法,它用于帮助我们更快捷的写代码。

Java中的元数据和元编程

注解的分类

一般常用的注解可以分为三类:

1、Java自带的标准注解
包括@Override、@Deprecated、@SuppressWarnings等,使用这些注解后编译器就会进行检查。

2、元注解
元注解是用于定义注解的注解,包括@Retention、@Target、@Inherited、@Documented、@Repeatable 等。
元注解也是Java自带的标准注解,只不过用于修饰注解,比较特殊。

3、自定义注解
用户可以根据自己的需求定义注解。

注解的使用

使用Java自带的注解

Java 自带的注解,就是 java.lang中定义的一套注解,以Override注解为例,使用方法如下:


    @Override         //在需要注解的方法上面@Override即可
    protected void onCreate() {
      
    }

常用的Java注解如下:

1、@Deprecated – 所标注内容不再被建议使用;
2、@Override – 只能标注方法,表示该方法覆盖父类中的方法;
3、@Documented --所标注内容可以出现在javadoc中;
4、@Inherited – 只能被用来标注“Annotation类型”,它所标注的Annotation具有继承性;
5、@Retention – 只能被用来标注“Annotation类型”,而且它被用来指定Annotation的RetentionPolicy属性;
6、@Target – 只能被用来标注“Annotation类型”,而且它被用来指定Annotation的ElementType属性;
7、@SuppressWarnings – 所标注内容产生的警告,编译器会对这些警告保持静默;
8、@interface – 用于定义一个注解;

其中,4、5、6、8多用于自定义注解,读者着重记一下。

自定义注解

在Java中,我们使用@interface注解来自定义一个注解,如下:


public @interface MyTestAnnotation {

}

此时,我们已经定义了一个注解MyTestAnnotation ,接着我们就可以在类或者方法上作用我们刚刚新建的注解:


@MyTestAnnotation
public class Test {
   @MyTestAnnotation
   public static void testString(){
   }
}

此时,我们已经自定义了一个注解,不过现在这个注解毫无意义。

要如何使注解工作呢?这就需要使用元注解了。

常用的元注解有@Retention、 @Target、 @Document、 @Inherited和@Repeatable五个。

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

在@Retention注解中使用枚举RetentionPolicy来表示注解保留时期:

  • @Retention(RetentionPolicy.SOURCE),注解仅存在于源码中,在class字节码文件中不包含
  • @Retention(RetentionPolicy.CLASS), 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
  • @Retention(RetentionPolicy.RUNTIME), 注解会在class字节码文件中存在,在运行时可以通过反射获取到

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

@Retention(RetentionPolicy.RUNTIME)
public @interface MyTestAnnotation {
}

@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类型,如下:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface MyTestAnnotation {
    
    }

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

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

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

注解的源码分析

我们以@Override注解为例,来分析其源码,想查看一个普通类一样,按住ctrl键点击@Override即可进入其源码,如下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

我们看到@Override注解就是通过@interface注解定义的一个普通注解,而我们知道,使用 @interface 定义注解时,意味着它实现了 java.lang.annotation.Annotation 接口,即该注解就是一个Annotation

注意:定义 Annotation 时,@interface 是必须的,它和我们通常的 implemented 实现接口的方法不同。Annotation 接口的实现细节都由编译器完成。通过 @interface 定义注解后,该注解不能继承其他的注解或接口。

下面我们来分析一下Annotation 类的源码,如下:


public interface Annotation {
    boolean equals(Object var1);

    int hashCode();

    String toString();

    Class<? extends Annotation> annotationType();
}

通过以上源码,我们知道注解本身就是Annotation接口的子接口,也就是说注解中其实是可以有属性和方法,但是接口中的属性都是static final的,对于注解来说没什么意义,而我们定义接口的方法就相当于注解的属性,也就对应了前面说的为什么注解只有属性成员变量,其实他就是接口的方法,这就是为什么成员变量会有括号,不同于接口我们可以在注解的括号中给成员变量赋值。

Java注解的架构

根据上述的源码分析,我们得出Java注解(Annotation)的架构如下:
在这里插入图片描述

0、注解是接口类,都继承自Annotation接口类

1、1 个 Annotation 和 1 个 RetentionPolicy 关联
可以理解为:每1个Annotation对象,都会有唯一的RetentionPolicy属性;

2、1 个 Annotation 和 1~n 个 ElementType 关联
可以理解为:对于每 1 个 Annotation 对象,可以有若干个 ElementType 属性;

3、Annotation 有许多实现类,包括:Deprecated, Documented, Inherited, Override 等等。
Annotation 的每一个实现类都和1个 RetentionPolicy 关联并且和 1~n 个 ElementType 关联。

注解的作用

在说注解的用途之前,我们先介绍下XML和注解区别:

  • 注解:是一种分散式的元数据,与源代码紧绑定。
  • xml:是一种集中式的元数据,与源代码无绑定

这部分多用于Java后台的配置项开发中,我们知道几年前服务器的配置项多存放在一个xml文件中,而spring 2.5 之后开始基于注解配置,从而实现了代替配置文件的功能。

注解的用途有很多,上面的只是一个简单的例子,总起起来,注解有如下四大部分作用:

1、生成文档,通过代码里标识的元数据生成javadoc文档。

2、编译检查,通过代码里标识的元数据让编译器在编译期间进行检查验证。

3、编译时动态处理,编译时通过代码里标识的元数据动态处理,例如动态生成代码。

4、运行时动态处理,运行时通过代码里标识的元数据动态处理,例如使用反射注入实例





好家伙,随手就是一个赞~

在这里插入图片描述
给作者买瓶咖啡提提神~




我的视频课

下面是我录制的一些视频课,欢迎大家围观~
《彻底搞定JVM》
JVM是Java中重要的也是较难理解的内容;
面试者对JVM的了解程度某种程度上反映了面试者技术深度,所以JVM也是面试时经常考察的内容;
本课程从JVM运行流程、数据运行时区域组成部分、类加载机制、垃圾回收机制、内存模型、常见面试题讲解等角度出发,帮你彻底搞定JVM,拿下心仪Offer;

《Android性能优化参考》
本课程包含了Android中的App启动优化、UI优化、内存优化、图片优化、耗电量等常见的性能优化场景,通过学习此课程,你将对整个Android性能优化体系有清晰的认识。

性能优化作为Android高级开发的必备技能,也是大厂面试必考的题目,是体现一个人技术深度最好的试金石。

《面试之排序算法》
排序算法是我们面试被问到最多的基础算法,本课程详细介绍了七种排序算法,包括插入排序、选择排序、冒泡排序、谢尔排序、快速排序、堆积排序和二路并归排序。每种算法都详细介绍了核心思想、详细步骤、时间复杂度和代码实现,希望帮助大家深入理解排序算法,搞定面试!

《Android HyBrid App开发实战》
本课程为Android HyBrid App开发实战课程,由浅入深,从三种App的历史和特点开始,介绍了Android WebView的使用、Java和JS交互的原生方式、著名的WebView安全漏洞、JSBridge的原理和使用,最后通过一个网上商城的实战综合全部内容,让同学们掌握并深入理解Android HyBrid App开发。

《AI导论》
介绍人工智能AI的诞生历史和到现在为止的不同发展阶段;介绍了AI领域中常见的名词概念和其关系,包括机器学习、深度学习、神经网络结构搜索 NAS、生成对抗网络 GAN等;最后对AI发展做出展望。
本课程属于导论课程,旨在帮助同学们从宏观层面把握AI,建立AI的知识体系。

《Java注解精讲》
本课程详细介绍了Java中的注解机制,包括注解的定义和分类,注解的使用和自定义,注解的源码和架构分析;
本课程语言简单凝练,视频短小精悍,让你一次彻底搞懂Java注解!

《Java反射精讲》
反射是Java中重要的也是较难理解的内容;
本课程从反射的定义、作用、原理和使用出发,全方位帮你彻底搞定反射;

  • 35
    点赞
  • 183
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以为您提供一个比较的日志注解的实现,供您参考和使用。以下是注解的定义和使用示例: ```java import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) @Documented public @interface LogAnnotation { /** * 日志描述信息 */ String description() default ""; /** * 是否打印方法执行时间 */ boolean printTime() default true; /** * 是否打印方法的参数和返回值 */ boolean printArgsAndReturn() default true; /** * 是否打印异常信息 */ boolean printException() default false; /** * 是否只打印异常信息 */ boolean printExceptionOnly() default false; /** * 是否忽略日志 */ boolean ignore() default false; } ``` 使用示例: ```java public class UserService { @LogAnnotation(description = "查询用户信息", printArgsAndReturn = true) public User getUserById(String userId) { // 查询用户信息的代码 return user; } @LogAnnotation(description = "创建用户", printArgsAndReturn = true) public void createUser(User user) { // 创建用户的代码 } @LogAnnotation(description = "更新用户信息", ignore = true) public void updateUser(User user) { // 更新用户的代码 } } ``` 在上述示例中,使用 `@LogAnnotation` 注解来标记需要记录日志的方法,并且可以通过注解的参数来指定日志的描述信息、是否打印方法执行时间、是否打印方法的参数和返回值、是否打印异常信息等。在实际使用中,您可以根据自己的需求来调整注解的参数,以达到最佳的日志记录效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不死鸟JGC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值