与注解的第一次接触
注解又称元数据(metadata),可以使代码更加简洁。
我们学习继承语法时,要重写父方法在方法上使用 @Override,这个注解是jdk提供的。
查看@override的源码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
通过使用这个注解,编译器可以帮助我们避免一些低级错误。
#语法介绍#
注解分类##
注解有以下三种分类:
- 元注解 :用来定义注解的注解
- 内建注解 :sun提供的注解 @override
- 自定义注解 : 除了sun提供的注解,各种框架和开发者写的注解
###元注解###
元注解用来定义注解的注解。
- @Target
- @Retention
- @Documented
- @Inherited
@Target
声明注解被使用在那里。ElementType参数可以使用的值有:
- CONSTRUCTOR : 注解被应用在构造器
- FIELD: 应用在 域声明
- LOCAL_VARIABLE :局部变量
- METHOD :方法
- PACKAGE : 包
- TYPE : 类,接口,注解,枚举
@Retention
声明注解信息保留到什么时候。RetentionPolicy 参数可使用的值有:
- SOURCE : 注解使用在源码阶段,注解在编译阶段丢弃
- CLASS : 注解在字节码中可用,但是在vm(虚拟机)中被丢弃
- RUNTIME : 保留到vm可以使用在运行时,可以使用反射读取。
@Documented
注解将被包含在 javadocs
@Inherited
允许子类继承父类的注解
###内建注解 ###
sun提供的注解
- @Override :检查重写父类方法
- @Deprecated :声明方法过时
- @SurppressWarnings :取消编译器警告
自定义注解###
定义自定义注解的语法:
@Target(ElementType.TYPE) // 选择你要自定义的注解的应用范围
@Retention(RetentionPolicy.RUNTIME) //选择你要自定义注解的使用时期
public @interface DBTable{
public String name() default "";
}
@interface 表示定义的是一个注解。
public String name() default “”; 表示注解有一个name 参数,默认为空。
使用我们自定义的注解
@DBTable(name = "User")
class User{
private String Name ;
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
}
到这里,我们就可以定义自己的注解了。不过到这里就结束了吗?
定义了注解,也使用了注解? 可以注解如何生效呢? 注解是如何能够做到我们想做的事情呢?这个也是我第一次接触注解时就有的想法,不过当时惭愧,没有去探究一下,只是使用提供的注解看了文档,就开始使用了,也没有怎么想去探究探究。
#注解处理器 #
注解能够起作用,原因就在于,每个注解都有自己的处理器,用来处理被注解的 类,方法,域声明… 。
##模拟注解处理器 ##
我们现在模拟一下,不正经的注解处理器,上面我们定义了注解@DBTable,这个注解用来注解类对应到数据的表。name属性声明数据库的表的名称。
public class Annotations {
public static void main(String [] args ) throws ClassNotFoundException{
Class<?> c1 = Class.forName("xuelongjiang.baseGrama.User");
DBTable table = c1.getAnnotation(DBTable.class);
if(table !=null){
System.err.println("注解生效");
System.err.println(table.name());
}
}
}
使用反射得到user类的注解,输出注解的name属性的值。这里的注解处理器,是一个类的main方法,我们只是模拟一下,处理注解。
使用 JSR 269 API处理注解
JSR 269 API(Pluggable Annotation Processing API)提供给我们一些接口用来处理被注解的类,方法… ,并且会加载我们的处理器,使我们的注解能够被处理。
在java 8 之前 使用的是apt,但是在java8 开始apt就被移除了。使用更加优雅的SR 269 API 来处理注解
###通过继承AbstractProcessor实现注解处理器 ###
@SupportedAnnotationTypes("DBTable")
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class DataProcess extends AbstractProcessor {
/**
* 注解处理过程被编译器调用
* 每轮处理注解都就被调用
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
//处理代码
return false;
}
}