网站首页 > java教程 正文
1 前言
很长一段时间以来,Java通过在其源代码中使用Javadoc注释标签,从而支持一种有限的元数据。使用@deprecated或@author这样的Javadoc标签,我们可以向一个类、方法或字段添加一些信息,具体方法是将信息放入到这些项上面的注释中。在这种情况下,这些信息主要对Javadoc文档的生成器有用,因为注释只存在于Java源代码中。然而,开发者很长时间以来期望一种方式能够生成元数据以用于其他的目的。实际上,有些工具已经开发了很长一段时间了,它们可以读取注释中的各种Javadoc式的标签,并且用它们做各种各样的事情,包括代码生成和文档。在Java 5.0中,有一种叫作注解的正式的、可扩展的元数据系统添加到了语言中,它提供这种源代码层级的功能,以及在运行时使用元数据的新功能。
2 基本语法
如下是一个注解的定义。注解的定义看起来很像接口的定义。
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {
}
注解放置在代码中,其前面有注解项,注解项使用一个@ 符号,后面跟着注解的类名。除了 @ 符号之外, @Idempotent 的定义看起来更像一个空接口。注解的定义也需要一些元注解(meta-annoation),比如 @Target 和 @Retention。@Target 定义你的注解可以应用在哪里(例如是方法还是字段)。@Retention 定义了注解在哪里可用,在源代码中(SOURCE),class文件(CLASS)中或者是在运行时(RUNTIME)。不包含任何元素的注解称为标记注解(marker annotation),例如上例中的 @Idempotent 就是标记注解。
下面是一个简单的注解。程序员可以使用该注解来标注满足特定用例的一个方法或者一组方法。而开发者在维护项目时可以轻松地找到用例用于更新,或者他们可以调试系统中业务逻辑。
package com.annotation;
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Idempotent {
/**
* 幂等名称,作为redis缓存Key的一部分。
*/
String value();
/**
* 幂等过期时间(秒),即:在此时间段内,对API进行幂等处理。
*/
long expireMillis() default 5;
}
注意 value和 expireMillis 与方法定义类似。由于编译器会对 value 进行类型检查,因此将跟踪数据库与用例文档和源代码相关联是可靠的方式。expireMillis 元素拥有一个 default 值,如果在注解某个方法时没有给出 expireMillis 的值。则该注解的处理器会使用此元素的默认值。
在下面的类中,有三个方法被注解为用例:
package com.annotation;
public class Test {
@Idempotent(value = "test1")
public void test1() {
}
@Idempotent(value = "test2", expireMillis = 10)
public void test2() {
}
}
注解的元素在使用时表现为 名-值 对的形式,并且需要放置在 @Idempotent 声明之后的括号内。在 test1() 方法的注解中,并没有给出 description 的值,所以在 @interface Idempotent 的注解处理器分析处理这个类的时候会使用该元素的默认值。
2.1 注解不支持继承
你不能使用 extends 关键字来继承 @interfaces。如果支持继承,就会大大减少打字的工作量并且使得语法更整洁。在 Java 的未来版本中,似乎没有任何关于让注解支持继承的提案。
3 标准注解
注解是Java 5中的一个新特性,最初有3个标准注解:Override、Deprecated和SupressWarnings,它们都定义在java.lang包中。
- Override
是一种标记注解类型,可应用于方法,它告诉编译器该方法是超类中一个方法的覆盖。这个注解类型可以防止程序员在覆盖方法时出错。
- Deprecated
是一个标记注解类型,可应用于某个方法或某个类型,表示该方法或该类型已被弃用。被弃用的方法或类型由程序员标记,以警告编写代码的用户不应使用或覆盖该方法以及使用或扩展该类型。
- SuppressWarnings
表示编译器应该针对注解的类或方法,抑制指定的警告类型。
4 元注解
Java 语言中目前有 5 种标准注解(前面介绍过),以及 5 种元注解。元注解用于注解其他的注解
注解 | 解释 |
@Target | 表示注解可以用于哪些地方。可能的 ElementType 参数包括: CONSTRUCTOR:构造器的声明 FIELD:字段声明(包括 enum 实例) LOCAL_VARIABLE:局部变量声明 METHOD:方法声明 PACKAGE:包声明 PARAMETER:参数声明 TYPE:类、接口(包括注解类型)或者 enum 声明 |
@Retention | 表示注解信息保存的时长。可选的 RetentionPolicy 参数包括: SOURCE:注解将被编译器丢弃 CLASS:注解在 class 文件中可用,但是会被 VM 丢弃。 RUNTIME:VM 将在运行期也保留注解,因此可以通过反射机制读取注解的信息。 |
@Documented | 将此注解保存在 Javadoc 中 |
@Inherited | 允许子类继承父类的注解 |
@Repeatable | 允许一个注解可以被使用一次或者多次(Java 8)。 |
大多数时候,程序员定义自己的注解,并编写自己的处理器来处理他们。
5 自定义注解
编译器对于元素的默认值有些过于挑剔。首先,元素不能有不确定的值。也就是说,元素要么有默认值,要么就在使用注解时提供元素的值。
这里有另外一个限制:任何非基本类型的元素, 无论是在源代码声明时还是在注解接口中定义默认值时,都不能使用 null 作为其值。这个限制使得处理器很难表现一个元素的存在或者缺失的状态,因为在每个注解的声明中,所有的元素都存在,并且具有相应的值。为了绕开这个约束,可以自定义一些特殊的值,比如空字符串或者负数用于表达某个元素不存在。
// annotations/SimulatingNull.java
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomAnnotation {
int id() default -1;
String description() default "";
}
这是一个在定义注解的习惯用法。
6 总结
注解是 Java 引入的一项非常受欢迎的补充,它提供了一种结构化,并且具有类型检查能力的新途径,从而使得你能够为代码中加入元数据,而且不会导致代码杂乱并难以阅读。Java 提供了很少的内置注解。这意味着如果你在别处找不到可用的类库,那么就只能自己创建新的注解以及相应的处理器。
7 最后的最后
为初学者提供学习指南,为从业者提供参考价值。我坚信码农也具有产生洞见的能力。关注【码农洞见】,一起学习和交流吧!
猜你喜欢
- 2024-09-21 人手必备!Java8中的注解,你必须知道的几点
- 2024-09-21 Java 进阶之 注解(java中注解如何实现的)
- 2024-09-21 java注解的使用(java注解的实现原理)
- 2024-09-21 不吹牛,撸个注解有什么难的(不吹牛的道理)
- 2024-09-21 终于弄懂了Spring@Component @Repository@Service的区别
- 2024-09-21 2020年最新Java全套教程注解(2020年最新兵役法)
- 2024-09-21 你知道Spring是如何处理注解的吗?
- 2024-09-21 注解梳理:深入理解Java注解类型(@Annotation)
- 2024-09-21 Java中的注解到底是如何工作的?(注解 java)
- 2024-09-21 JAVA 注解的几大作用及使用方法详解
你 发表评论:
欢迎- 最近发表
-
- class版本不兼容错误原因分析(class更新)
- 甲骨文Oracle公司为Java的最新LTS版本做出改进
- 「版本发布」Minecraft Java开发版 1.19.4-pre1 发布
- java svn版本管理工具(svn软件版本管理)
- 我的世界1.8.10钻石在第几层(我的世界1.7.2钻石在哪层)
- Java开发高手必备:在电脑上轻松切换多个JDK版本
- 2022 年 Java 开发报告:Java 8 八年不到,开发者都在用什么?
- 开发java项目,选择哪个版本的JDK比较合适?
- Java版本选型终极指南:8 vs 17 vs 21特性对决!大龄程序员踩坑总结
- POI Excel导入(poi excel导入附件)
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)