注解
注解
本文写作目的是为了做笔记,部分概念性资料来源于网络,如有侵权,请联系我删除
什么是注解
Java 注解(Annotation)又称 Java 标注,是JDK5.0引入的一种注释机制。
Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。
注解的作用
- 用来充当注释作用(仅仅是一个文字说明) 如@Deprecated写在某个方法上表示该方法已过期不推荐使用,但是你想用也可以用
- 用来做代码的检测(验证) 如@Override
- 可以携带一些信息
注解可携带的信息的类型
注解可以携带信息,也可以不携带。如果携带信息,则必须是如下的类型
- 基本数据类型
- String类型
- 枚举类型
- 注解类型
- 数组类型(数组内的数据必须是如上的4种类型)
自定义注解
一个简单的示例
package study.annotation;
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 注解学习
* @author Administrator
*/
@Target({FIELD, METHOD})
@Retention(RetentionPolicy.SOURCE)
@Inherited
@Documented
public @interface TestAnnotation01 {
// 注解的方法
public abstract String test() default "aaa";
}
注意:
-
注解使用
@interface声明,修饰符仅允许使用public -
注解的定义形式一般如下
modifier type attributeName() default "default value";示例如下
public abstract String test() default "aaa";- 上面的
attributeName称之为注解的方法(也有人称之为注解的属性,但是无论是从它的组成形式上来看还是它可以被public abstract修饰来看,这个东西更像是一个方法。另外还有一点可以佐证这个观点,那就是当你利用反射技术来获取注解里面的值时,你是通过class.getMethod方法来获取到获取attributeName的,而不是class.getField。可以从文章最后的示例里面找到) - 上面的
type称之为注解的类型,仅允许使用基本类型,字符串,枚举,注解或其一维数组 - 注解的方法前面仅允许使用
public abstract修饰,所以也可以省略不写 - 注解的方法可以有默认值,也可以不给默认值,默认值使用
default关键字说明
- 上面的
-
自定义的注解需要使用
元注解来说明,如下@Target({FIELD, METHOD}) @Retention(RetentionPolicy.SOURCE) @Inherited @Documented
元注解
元注解是用来说明注解的注解(Java已经提供好了的),每个自定义的注解都需要用元注解来说明其自身的一些特性。元注解存于java.lang.annotation包下,一共有四个。分别是@Target、@Retention、@Inherited、@Documented。
@Target
定义了注解的作用目标,源码为
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
使用@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)
@Retention
定义了注解的保留策略,即注解可以被保留在那个阶段
我们都知道Java代码的执行过程如下
源代码文件--->编译--->字节码文件--->加载--->内存执行
这个过程在@Retention注解里对应如下
SOURCE CLASS RUNTIME
对应如下
// 注解仅存在于源码中,在class字节码文件中不包含
@Retention(RetentionPolicy.SOURCE)
// 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
@Retention(RetentionPolicy.CLASS)
// 注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
@Inherited
说明子类可以继承父类中的该注解
@Document
说明该注解将被包含在javadoc中
使用注意
- 如果注解中只有一个方法,并且方法名为
value,则在使用的时候可以不传方法名,只传递值即可 - 如果传递的是一个数组,数组内只有一个元素,则可以省略{}
- 如果注解中的方法为两个以上,则每一个方法名都需要写
利用反射技术获取注解里的值
一个简单的示例,需要一个注解类TestAnnotation01、一个普通的Java类Person以及一个main方法
注解类TestAnnotation01
package study.annotation;
import static java.lang.annotation.ElementType.*;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 注解学习
* @author Administrator
*/
@Target({FIELD, METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface TestAnnotation01 {
String[] value();
}
Person类
package study.annotation;
public class Person {
@TestAnnotation01({"lmw", "18", "男"})
private String name;
}
main方法
package study.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 利用反射技术获取Person类字段上的注解里面的值
* @author Administrator
*/
public class TestMain {
public static void main(String[] args) {
try {
// 1.获取Person类的类类型
Class clazz = Person.class;
// 2.获取Person类的属性对象
Field field = clazz.getDeclaredField("name");
// 3.获取字段上的注解对象
Annotation a = field.getAnnotation(TestAnnotation01.class);
// 4.获取注解的类类型
Class aClazz = a.getClass();
// 5.获取注解里的方法
Method method = aClazz.getMethod("value");
// 6.使用invoke方法执行value方法获取返回值
String[] values = (String[])method.invoke(a);
// 7.展示values的值
for(String value:values) {
System.out.println(value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

浙公网安备 33010602011771号