什么是注解?
Java中提供了Annotation功能,可用于类、构造方法、成员变量、方法、参数等的声明中,该功能并不影响程序的运行。
为什么要学习注解?
最近在学习spring、mybatis等框架,里面频繁使用注解。学习注解可以看懂框架相关的代码。
JDK自带注解
- @Deprecated
- @Override
- @SuppressWarnings
元注解
用来注解注解的注解。
@Target:设置annotation适用的程序元素的种类
取值范围如下:
枚举常量 | 说明 |
---|---|
ElementType.ANNOTATION_TYPE | 表示用于Annotation类型 |
ElementType.CONSTRUCTOR | 表示用于构造方法 |
ElementType.TYPE | 表示用于类、接口和枚举,以及Annotation类型 |
ElementType.FIELD | 表示用于成员变量和枚举常量 |
ElementType.METHOD | 表示用于方法 |
ElementType.PARAMETER | 表示用于参数 |
ElementType.LOCAL_VARIABLE | 表示用于局部变量 |
ElementType.PACKAGE | 表示用于包 |
@Retention:设置Annotation的有效范围。
取值范围如下:
枚举常量 | 说明 |
---|---|
RetentionPolicy.SOURCE | 表示不编译Annotation到类文件中,有效范围最小 |
RetentionPolicy.CLASS | 表示编译Annotation到类文件中,但是在运行时不加载Annotation到JVM |
RetentionPolicy.RUNTIME | 表示在运行时加载Annotation到JVM中,有效范围最大 |
@Documented
在生成javadoc时,会包含这个注解。
@Inherited
允许子类继承
@Repeatable
从Java SE 8开始被引入。如字面意思,在同一个声明中可以多次应用。例子如下:
@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }
自定义注解
先看一个例子:
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface StudentInfo {
String school();
String student();
int age() default 18;
}
自定义注解的格式:
public @interface 注解名称 {
定义体(注解成员信息,包括类型和名称)
}
定义注解主要分为以下两步:
- 通过@interface关键字声明注解名称、注解成员属性等。
- 通过元注解对自定义注解的功能和范围进行约束
注解的成员
成员类型:
- 所有的基本数据类型
- String
- Class
- enumerated
- annotation
- 以上所有类型的数组
成员名称:如果所定义的Annotation中只包含一个成员,通常将其命名为value。
public @interface Example{
String value();
}
为成员设置默认值,例如
public @interface Example1{
String name() default "lightning";
int age() default 18;
}
注解元素必须有确定的值,要么在定义注解的默认值中指定,要么在使用注解时指定,非基本类型的注解元素的值不可为null。
注解的使用
新建一个注解
import java.lang.annotation.*;
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Description {
String value();
}
新建一个接口/类,并加上注解。
@Description("I am interface")
public interface Person {
@Description("I am interface method")
public String name();
public int age();
public void sing();
}
用反射的方式读取注解
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class ParseAnn {
public static void main(String[] args) {
//1.使用类加载器加载类
try {
Class c=Class.forName("com.ann.test.Person");
//2.找到类上面的注解
boolean isExist=c.isAnnotationPresent(Description.class);
if(isExist) {
//3.拿到注解实例
Description d=(Description) c.getAnnotation(Description.class);
System.out.println(d.value());
}
//4.找到方法上的注解
Method[] ms=c.getMethods();
for(Method m:ms) {
boolean isMExist=m.isAnnotationPresent(Description.class);
if(isMExist) {
Description d=(Description) m.getAnnotation(Description.class);
System.out.println(d.value());
}
}
//另外一种解析方法
for(Method m:ms) {
Annotation[] as=m.getAnnotations();
for(Annotation a:as) {
if(a instanceof Description) {
Description d=(Description) a;
System.out.println(d.value());
}
}
}
}catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
}
【参考资料】
Oracle官方文档
极客学院:“Java注解技术详解”课程
《Java从入门到精通》, 清华大学出版社