Java 注解又称Java标注,是 Java5 版本开始支持加入源代码的特殊语法元数据。 Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容。
Java注解-维基百科
本文介绍了Java注解的申明和定义方法。
基本语法
声明注解与元注解
先给出一个申明注解的例子:
1 | (ElementType.METHOD) |
@Target
和@Retention
是由Java提供的元注解,所谓元注解就是标记其他注解的注解,下面分别介绍:上述例子使用@interface申明了一个注解Test,并使用@Target
注解传入ElementType.METHOD
参数来标明@Test只能用于方法上,@Retention(RetentionPolicy.RUNTIME)
则用来表示该注解生存期是运行时。
@Target 表示该注解用于什么地方,可能的 ElemenetType 参数包括:
- ElemenetType.CONSTRUCTOR 构造器声明
- ElemenetType.FIELD 域声明(包括 enum 实例)
- ElemenetType.LOCAL_VARIABLE 局部变量声明
- ElemenetType.METHOD 方法声明
- ElemenetType.PACKAGE 包声明
- ElemenetType.PARAMETER 参数声明
- ElemenetType.TYPE 类,接口(包括注解类型)或enum声明
@Retention 表示在什么级别保存该注解信息。可选的 RetentionPolicy 参数包括:
- RetentionPolicy.SOURCE 注解将被编译器丢弃
- RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃
- RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
@Documented 将此注解包含在 javadoc 中
@Inherited 允许子类继承父类中的注解
注解元素及其数据类型
上述所给例子@Test内部没有定义其他元素,所以@Test也称为标记注解(marker annotation),但在自定义注解中 ,一般都会包含一些元素以表示某些值,方便处理器使用,如下例:
1 | //只能应用于类上 (ElementType.TYPE) |
其在类上的使用示例为:上述定义一个名为DBTable的注解,我们声明了一个String类型的name元素,其默认值为””空字符。
1 | //在类上使用该注解 |
所有基本类型(int,float,boolean,byte,double,char,long,short)注解中支持的元素数据类型有:
- String
- Class
- enum
- Annotation
- 上述类型的数组
(注解也可以作为注解的元素类型,可以使用嵌套注解;另外,null不能作为元素默认值)
注解编译后自动继承java.lang.annotation.Annotation接口
1 | package com.zejian.annotationdemo; |
注解与反射机制(注:所有的Java注解都继承了Annotation接口)
我们知道Java所有注解都继承了Annotation接口,也就是说 Java使用Annotation接口代表注解元素,该接口是所有Annotation类型的父接口。
同时为了运行时能准确获取到注解的相关信息,Java在java.lang.reflect 反射包下新增了AnnotatedElement接口,它主要用于表示目前正在 VM 中运行的程序中已使用注解的元素,通过该接口提供的方法可以利用反射技术地读取注解的信息。
反射包的Constructor类、Field类、Method类、Package类和Class类都实现了AnnotatedElement接口:
Class:类的Class对象定义
Constructor:代表类的构造器定义
Field:代表类的成员变量定义
Method:代表类的方法定义
Package:代表类的包定义
下面是AnnotatedElement中相关的API方法,以上5个类都实现以下的方法:
返回值 | 方法名称 | 说明 |
---|---|---|
getAnnotation(Class annotationClass) | 该元素如果存在指定类型的注解,则返回这些注解,否则返回 null。 | |
Annotation[] | getAnnotations() | 返回此元素上存在的所有注解,包括从父类继承的 |
boolean | isAnnotationPresent(Class extends Annotation> annotationClass) | 如果指定类型的注解存在于此元素上,则返回 true,否则返回 false。 |
Annotation[] | getDeclaredAnnotations() | 返回直接存在于此元素上的所有注解,注意,不包括父类的注解,调用者可以随意修改返回的数组;
这不会对其他调用者返回的数组产生任何影响,没有则返回长度为0的数组 |
注解与反射示例
反射注解,那么保留策略必须是Runtime,也就是@Retention(RetentionPolicy.RUNTIME)
①定义一个注解类
1 | (RetentionPolicy.RUNTIME) |
1 | public class MyBean { |
③在main方法里面反射注解②再定义一个类使用注解类
1 | public static void main(String[] args) { |
注:更多示例请参见:输出结果为:20