一、定义
用来说明程序地一个标识,给计算机看的。注解也叫元数据,是一种代码级别的说明。它是JDK1.5之后引入地一个特性,是一种特殊地接口,可以使用在字段、类、方法、包参数等上面。
注意:注解本身并没有任何功能,仅仅起到一个标识性地作用。我们通过反射获得注解,再根据是否有这个注解、注解中的一些属性去判断,执行哪种业务逻辑。
二、自定义注解
1) 语法
注解的关键字为@interface。在底层实现上,所有定义的注解都会自动继承java.lang.annotation.Annotation接口。
//此处为元注解
public @interface MyAnnotation {
//此处为属性列表
String name() ;
int age() default 18;
String[] favoriteFood();
}
2)属性
- 注解的属性本质为接口中的抽象方法,默认值用default指定
- 属性只能是以下数据类型
a. 基本数据类型
b. String
c. 枚举
d. 注解
e. 以上类型的数组 - 如果定义了属性,在使用的时候需要给属性赋值
- 如果只有一个属性, 可以把这个属性名字定义为value,这样使用的时候可以省略属性名
- 数组属性的值要用 {} 包裹,如果数组只有一个值,那么 {} 可以省略
- 如果注解本身没有属性,那么在使用注解的时候可以省略(),直接写为:@注解名,它和标准语法@注解名()等效
3)元注解
用于描述注解的注解
a. @Targer: 描述该注解的作用范围, 用枚举类ElementType定义类型如下
public enum ElementType {
/** Class, interface (including annotation type), or enum declaration */
TYPE,
/** Field declaration (includes enum constants) */
FIELD,
/** Method declaration */
METHOD,
/** Formal parameter declaration */
PARAMETER,
/** Constructor declaration */
CONSTRUCTOR,
/** Local variable declaration */
LOCAL_VARIABLE,
/** Annotation type declaration */
ANNOTATION_TYPE,
/** Package declaration */
PACKAGE,
/**
* Type parameter declaration
*
* @since 1.8
*/
TYPE_PARAMETER,
/**
* Use of a type
*
* @since 1.8
*/
TYPE_USE
}
b. @Retention: 描述注解被保留的阶段
RetentionPolicy.RUNTIME: 会保留到class字节码文件中,被jvm读取。 基本用该类型
c. @Documented: 描述注解是否被抽取到api文档中。一般不用
d. @Inherited: 描述注解是否可以被继承。一般不继承
三、自定义注解的使用
- 定义注解:相当于定义标记;
- 配置注解:把标记打在需要用到的程序代码中;
- 解析注解:在编译期或运行时检测到标记,并进行特殊操作。
public class AnnationClientTest {
@Test
public void testAnnation() throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException {
Class studentClass = Class.forName("com.javalearning.School");
Field[] snames = studentClass.getDeclaredFields();
for (Field sn : snames) {
if (sn.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation annotation = sn.getAnnotation(MyAnnotation.class);
if (annotation != null) {
System.out.println(annotation.name() + annotation.age() + annotation.favoriteFood());
}
}
}
System.out.println(studentClass);
}
}
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
//元注解
public @interface MyAnnotation {
//属性列表
String name() ;
int age() default 18;
String[] favoriteFood();
}
public class School {
@MyAnnotation(name="Vivi", favoriteFood = {"banana, pineapple, cucumber"})
private String schoolName;
...
}
- 如果要获得的注解是配置在方法上,那么要从Method对象上获取;如果配置在属性上,就从该属性对应的Field对象上去获取,如果配置在类型上,需要从Class对象上去获取。
- isAnnotationPresent()方法是判断该元素上是否配置有某个指定的注解;
- getAnnotation()方法是获取该元素上指定的注解。之后再调用该注解的注解类型元素方法就可以获得配置时的值数据;
- 反射对象上还有一个方法getAnnotations(),该方法可以获得该对象身上配置的所有的注解。它会返回给我们一个注解数组,需要注意的是该数组的类型是Annotation类型,这个Annotation是一个来自于java.lang.annotation包的接口。