分类
大致分为三类:自定义注解、JDK内置注解、还有第三方框架提供的注解。
- 自定义注解就是我们自己写的注解,比如@UserLog
- JDK内置注解,比如@Override检验方法重写,@Deprecated标识方法过期等
- 第三方框架定义的注解比如SpringMVC的@Controller等
使用位置
- 类
- 方法
- 形式参数
作用
像一个标签,贴在一个类、一个方法或者字段上。目前是为当前读取该注解的程序提供判断依据及少量附加信息。
注解的本质
自己写一个java注解
反编译后看到@interface 变成了 interface接口还继承了Annotation类:
并且还可以在注解中写方法:可以省略掉public abstract
在使用注解时,也可以给getValue()赋值:
@MyAnnotation(getValue = "annotation on Class")
public class AnnotationDemo {
@MyAnnotation(getValue = "annotation on Field")
public String name;
@MyAnnotation(getValue = "annotation on Method")
public void method() {}
@MyAnnotation()
public void method2() {}
}
类似于getValue()这种,应该被称为属性,另外还可以给属性指定默认值
public @interface MyAnnotation {
String getValue() default "no description";
}
用反射获取注解信息
public class AnnotationTest {
public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
// 获取类上的注解
Class<AnnotationDemo> clazz = AnnotationDemo.class;
MyAnnotation annotationOnClass = clazz.getAnnotation(MyAnnotation.class);
System.out.println(annotationOnClass.getValue());
// 获取属性上的注解
Field name = clazz.getField("name");
MyAnnotation annotationOnFiled = name.getAnnotation(MyAnnotation.class);
System.out.println(annotationOnFiled.getValue());
// 获取方法上的注解
Method method = clazz.getMethod("method", null);
MyAnnotation annotationOnMethod= method.getAnnotation(MyAnnotation.class);
System.out.println(annotationOnMethod.getValue());
// 获取默认注解
Method method1 = clazz.getMethod("method2", null);
MyAnnotation annotationOnMethod2 = method1.getAnnotation(MyAnnotation.class);
System.out.println(annotationOnMethod2.getValue());
}
}
输出结果:
属性的数据类型及特别的属性:value和数组
属性的数据类型
- 八种基本数据类型
- String
- 枚举
- Class
- 注解类型
- 以上类型的一维数组
/**
* @author qiyu
*/
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
// 8种基本数据类型
int intValue();
long longValue();
// ...其他类型省略
// String
String name();
// 枚举
CityEnum cityName();
// Class类型
Class<?> clazz();
// 注解类型
MyAnnotation2 annotation2();
// 以上几种类型的数组类型
int[] intValueArray();
String[] names();
// ...其他类型省略
}
@interface MyAnnotation2 {
}
enum CityEnum {
BEIJING,
HANGZHOU,
SHANGHAI;
}
/**
* @author qiyu
*/
@MyAnnotation(
// 8种基本类型
intValue = 1,
longValue = 0L,
// String
name = "annotation on class",
// 枚举
cityName = CityEnum.BEIJING,
// Class
clazz = Demo.class,
// 注解
annotation2 = @MyAnnotation2,
// 一维数组
intValueArray = {1, 2},
names = {"Are", "you", "OK?"}
)
public class Demo {
// 省略...
}
- 如果注解的属性只有一个,并且叫value,那么使用该注解时,可以不用指定属性名,因为默认就是给value赋值
- 但是注解的属性有多个情况下,无论是否叫value,都必须写明属性的对应关系。
- 如果数组的元素只有一个,可以省略花括号{}
- 可以用属性赋值常量类为注解