什么是注解
Annotation是一种新的数据类型,和接口很相似,与类、接口、枚举是同级别的。
相当于一种标记,以 @ 开头,可以声明类、属性、方法、参数等的前面。用来对元素进行说明、标注、实现特定的功能
作用:
1、编写文档:根据注解生成文档
2、代码分析:通过注解使用反射对代码进行分析
3、编译检查:通过注解让编译器能够实现基本类型检查,如Override
JDK预定义的注解
在 java.lang 包中
注解 | 作用 |
---|---|
@Override | 方法前面,重写父类的方法 |
@Deprecated | 类、属性、方法前面,表示过时的,不建议使用的 |
@SuppressWarning | 类、属性、方法前面,表示关闭警告信息 |
package cn.xxx.annotation;
import java.util.Date;
@SuppressWarnings("all")
public class AnnoDemo2 {
@Override
public String toString() {
return super.toString();
}
@Deprecated//过期注解
public void show1(){
//有缺陷
}
public void show2(){
//替代show1方法
}
public void demo(){
show1();
Date date = new Date();
}
}
自定义注解
使用 @interface
+ 元注解
// 元注解
public @interface 注解名 {
// 抽象方法或者叫属性列表
}
元注解:标记在注解上的注解
元注解 | 作用 |
---|---|
@Target | 定义注解的作用域,即可以被标记在哪些元素上,如类、方法等。省略时表示可以在任何元素前 |
@Retention | 定义注解的生命周期,SOURCE、CLASS、RUNTIME,保留在编译,保留在类中,一般用RUNTIME |
@Documented | 当使用 javadoc 生成文档时是否包含注解 |
@Inheried | 允许子类继承父类注解 |
注解最终编译为:
public interface MyAnno extends java.lang.annotation.Annotation {
}
所以注解的本质就是一个接口,该接口默认继承 Annotation 接口
package cn.xxx.annotation;
import java.lang.annotation.*;
@Target({
ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface MyAnno3 {
}
使用注解
语法:
@注解名(属性名=属性值,属性名=属性值)
- 在使用注解时需要为注解中的抽象方法指定返回值,也称为为注解指定属性值。
- 属性名就是注解中抽象方法的名称
package cn.xxx.annotation;
public @interface MyAnno {
int value();
Person per();
MyAnno2 anno2();
String[] strs();
/*String name() default "张三";*/
/*String show2();
Person per();
MyAnno2 anno2();
String[] strs();*/
}
package cn.xxx.annotation;
@MyAnno(value=12,per = Person.P3,anno2 = @MyAnno2,strs={
"bbb","aaa"})
@MyAnno3
public class Worker {
@MyAnno3
public String name = "aaa";
@MyAnno3
public void show () {
}
}
解析注解
对于生命周期为运行期间(RUNTIME)的注解。解析注解就是获取注解中定义的属性值。有三步:
- 获取注解定义的位置(Class,Method,Field)的对象
- 获取指定的注解
- getAnnotation(Class)
//其实就是在内存中生成了一个该注解接口的子类实现对象 public class ProImpl implements Pro{ public String className(){ return "cn.itcast.annotation.Demo1"; } public String methodName(){ return "show"; } }
- 调用注解中的抽象方法获取配置的属性值。
举例:
// 1、获取类上的注解
Class cls = Student.class;
// 2、获取该类Student上的所有注解,不一定获取类上的注解,也可以获取方法上的注解,这时候就是 `method.getAnnotation()`
Annotation[] annotation = cls.getAnnotations();
// 仅获取该类上的Pro注解
Pro annotation = cls.getAnnotation(Pro.class);
// 3、获取注解上的属性方法
String className = annotation.className() // cn.xxx.annotation.Demo1
String className = annotation.methodName() // show
...
总结
注解是一个类似标签的东西,比如给一个函数打上 Check 的注解,代表这个函数可以被检查,那么对应的检查程序可以通过识别这个 Check 注解来执行对应的程序,如果没有这个检查程序,那么注解本身并没有什么意义,就和注释一样。
1、大多数时候,我们只会使用注解,而不是自定义注解
2、注解主要给谁用?1. 编译器 2.解析程序
3、注解不是程序的一部分,只是一个类似标签的东西