目录
前言
一、概述
二、Java预置注解
三、自定义注解
四、元注解
1. @Retention
2. @Target
3. @Documented
4. @Inherited
5. @Repeatable
总结
前言
随着Java语言的发展,注解(Annotations)逐渐成为了Java编程不可或缺的一部分。自从JDK 1.5引入注解以来,这一功能极大地丰富了Java的元数据表达能力,使得在不改变原有代码逻辑的前提下,可以在代码中嵌入补充信息。注解不仅能够为代码添加元数据,还可以在框架实现中发挥重要作用。本文旨在详细介绍Java注解的相关概念,包括Java预置注解、自定义注解、元注解以及如何通过反射获取注解信息等内容,帮助大家更好地理解和应用注解。
一、概述
什么是注解? 注解是JDK1.5才引入的。 注解可以标注在 类上,属性上,方法上 等。 注解可以做到在不改变代码逻辑的前提下在代码中嵌入补充信息。注解与注释是有区别的,其中注释是给程序员看的,编译器编译时会忽略注释;注解是给编译器看的,或给其它程序看的,程序根据有没有这个注解来决定不同的处理方式。注解在一些框架的实现上来说是非常重要的。
二、Java预置注解
Java为程序员提供了一些内置的注解,下面列举了几个常见的注解:
注解 | 描述 |
---|---|
@Deprecated | 用来标记过时的元素,在编译阶段遇到这个注解时会发出提醒警告,告诉开发者正在调用一个过时的元素比如过时的类、过时的方法、过时的属性等。 |
@Override | 修饰实例方法,则该方法必须是个重写方法,否则就会编译失败。 |
@SuppressWarnings | 抑制警告的注解,在实际开发中,建议尽量不要忽略警告,而是真正的去解决警告。 @SuppressWarnings("rawtypes"):抑制未使用泛型的警告 @SuppressWarnings("resource"):抑制未关闭资源的警告 @SuppressWarnings("deprecation"):抑制使用了已过时资源时的警告 @SuppressWarnings("all"):抑制所有警告 |
@FunctionalInterface | “函数式接口”的注解,这个是 JDK1.8 版本引入的新特性。使用@FunctionalInterface标注的接口,则该接口就有且只能存在一个抽象方法,否则就会发生编译错误(注意:接口中的默认方法或静态方法可以有多个)。 |
补充:在Java中,函数式接口(Functional Interface)是指只有一个抽象方法的接口。这种接口可以使用lambda表达式或方法引用来创建实现对象。
三、自定义注解
我们可以使用 @interface 来定义注解。 默认情况下注解可以出现在类上、方法上、属性上、构造方法上、方法参数上等...... 所有自定义的注解,它的父类是:java.lang.annotation.Annotation。注解可以定义属性,不过属性定义时,属性名后面必须加一个小括号。 属性的类型只能是byte,short,int,long,float,double,boolean,char、String、Class、枚举类型、注解类型和以上所有类型的一维数组形式。注解在使用时必须给属性赋值,除非使用了default关键字为属性指定了默认值。 如果属性只有一个,并且属性名是value时,使用注解时value可以省略不写。 如果属性是一个数组,使用注解时,数组值只有一个,数组的大括号是可以省略的。下图展示了注解编译成class文件后本质是一个接口。
四、元注解
用来标注注解的注解叫做元注解,元注解也是JDK内置的注解。常用的元注解有:
注解 | 描述 |
---|---|
@Retention | 设置注解的保持性 |
@Target | 设置注解可以出现的位置 |
@Documented | 设置注解是否可以生成到帮助文档中 |
@Inherited | 设置注解是否支持继承 |
@Repeatable | 设置注解在某一个元素上是否可以重复使用(Java8的新特性。) |
1. @Retention
Retention英文意思有保留、保持的意思,它表示注解存在阶段是保留在源代码(编译期),字节码(类加载)或者运行时(JVM中运行)。在@Retention注解中使用枚举RetentionPolicy来表示注解保留时期。下面列举出了这三种策略:
注解形式 | 描述 |
---|---|
@Retention(RetentionPolicy.SOURCE) | 注解仅存在于源代码中,在字节码文件中不包含。 |
@Retention(RetentionPolicy.CLASS) | 注解在字节码文件中存在,但运行时无法获得(默认)。 |
@Retention(RetentionPolicy.RUNTIME) | 注解在字节码文件中存在,且运行时可通过反射获取。 |
2. @Target
该注解使用ElementType枚举类型用于描述注解可以出现的位置, ElementType有如下枚举值:
注解形式 | 描述 |
---|---|
@Target(ElementType.TYPE) | 作用于接口、类、枚举、注解 |
@Target(ElementType.FIELD) | 作用于属性、枚举的常量 |
@Target(ElementType.METHOD) | 作用于方法 |
@Target(ElementType.PARAMETER) | 作用于方法参数 |
@Target(ElementType.CONSTRUCTOR) | 作用于构造方法 |
@Target(ElementType.LOCAL_VARIABLE) | 作用于局部变量 |
@Target(ElementType.ANNOTATION_TYPE) | 作用于注解 |
@Target(ElementType.PACKAGE) | 作用于包 |
@Target(ElementType.TYPE_PARAMETER) | 作用于泛型,即泛型方法、泛型类和泛型接口 |
@Target(ElementType.TYPE_USE) | 作用于任意类型 |
3. @Documented
Documented的英文意思是文档。使用javadoc.exe工具可以从程序源代码中抽取类、方法、属性等注释形成一个源代码配套的API帮助文档,而该工具抽取时默认不包括注释内容。如果使用的注解被@Documented标注,那么该注解就能被javadoc.exe工具提取到API文档。
4. @Inherited
Inherited的英文意思是继承,但是这个继承和我们平时理解的继承大同小异,一个被@Inherited注解了的注解修饰了一个父类,则它的子类也继承了父类的注解。
5. @Repeatable
Repeatable表示可重复的含义,该注解属于JDK1.8版本的新特性。可重复的一个示例如下图所示:
五、反射注解
反射注解用到的方法具有相似的名称,其中getAnnotations()获取所有注解,getAnnotation(Class annotationClass)获取指定的某个注解,isAnnoationPresent(Class annotationClass)检查指定类型的注解是否存在。下面是AI给出的几个常用的反射注解的方法:
总结
本文探讨了Java注解的各个方面,从Java注解的引入背景到常见预置注解的介绍,再到自定义注解的定义方法和元注解的使用。我们了解到注解不仅仅是代码中的装饰品,它们可以深刻影响到代码的编译和运行时行为。通过元注解,我们可以控制注解的生命周期以及它们的作用域。最后,我们还讨论了如何利用反射技术来操作注解,从而在运行时获取更多的元数据信息。掌握注解的使用不仅可以提高代码的可维护性和可扩展性,还能促进对现代Java框架的理解与开发。希望本文能够帮助大家在实际开发中更加灵活地运用注解这一强大工具。