今天来说说注解,小小的东西可藏着大大的能量,一起看看吧。
注解,在我看来它是一种信息描述,不影响代码执行,但是可以用来配置一些代码或者功能。
常见的注解比如@Override
,代表重写方法,看看它是怎么生成的:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
可以看到Override被@interface
所修饰,代表注解,同时上方还有两个注解@Target和@Retention,这种修饰注解的注解叫做元注解
,很好理解吧,就是最基本的注解呗。java中一共有四个元注解:
@Target
:表示注解对象的作用范围。@Retention
:表示注解保留的生命周期@Inherited
:表示注解类型能被类自动继承。@Documented
:表示含有该注解类型的元素(带有注释的)会通过javadoc或类似工具进行文档化。target,表示注解对象的作用范围,比如Override
注解所标示的就是ElementType.METHOD
,即所作用的范围是方法范围,也就是只能在方法头上加这个注解。另外还有以下几个修饰范围参数:
TYPE
:类、接口、枚举、注解类型。FIELD
:类成员(构造方法、方法、成员变量)。METHOD
:方法。PARAMETER
:参数。CONSTRUCTOR
:构造器。LOCAL_VARIABLE
:局部变量。ANNOTATION_TYPE
:注解。PACKAGE
:包声明。TYPE_PARAMETER
:类型参数。TYPE_USE
:类型使用声明。比如ANNOTATION_TYPE就是表示该注解的作用范围就是注解,哈哈,有点绕吧,看看Target注解的代码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
带了一个ElementType
类型的参数,也就是上面说到的作用范围参数,另外还被Target注解修饰了,传的参数就是ANNOTATION_TYPE
,也就是我注解我自己,我设置我自己的作用范围是注解。大家自己绕一下。。
表示注解保留的生命周期,或者说表示该注解所保留的时长,主要有以下几个可选参数:
SOURCE
:仅存在Java源文件,经过编译器后便丢弃相应的注解。适用于一些检查性的操作,比如@Override。CLASS
:编译class文件时生效,存在Java源文件,以及经编译器后生成的Class字节码文件,但在运行时VM不再保留注释。这个也是默认的参数。适用于在编译时进行一些预处理操作,比如ButterKnife的@BindView,可以在编译时生成一些辅助的代码或者完成一些功能。RUNTIME
:存在源文件、编译生成的Class字节码文件,以及保留在运行时VM中,可通过反射性地读取注解。适用于一些需要运行时动态获取注解信息,类似反射获取注解等。表示注解类型能被类自动继承。这里需要注意两点:
类
。也就是说只有在类集成关系中,子类才会集成父类使用的注解中被@Inherited所修饰的那个注解。其他的接口集成关系,类实现接口关系中,都不会存在自动继承注解。自动继承
。也就是说如果父类有@Inherited
所修饰的那个注解,那么子类不需要去写这个注解,就会自动有了这个注解。还是看个例子:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited
public @interface MyInheritedAnnotation {
//注解1,有Inherited注解修饰
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
//注解2,没有Inherited注解修饰
}
@MyInheritedAnnotation
@MyAnnotation
public class BaseClass {
//父类,有以上两个注解
}
public class ExtendClass extends BaseClass {
//子类会继承父类的MyInheritedAnnotation注解,
//而不会继承MyAnnotation注解
}
表示拥有该注解的元素可通过javadoc
此类的工具进行文档化,也就是说生成JavaAPI文档的时候会被写进文档中。
主要有以下几个用处:
规律性的代码
。java代码
,减轻开发者的工作量。很多开源库都会用到注解,就是为了方便我们开发,这也是开源库的初衷,所以注解基本上都是框架必选。比如ButterKnife
,我们可以通过@BindView
注解就完成了view的资源id绑定。其实就是框架在编译时就生成了一些类,然后通过反射或者一些工具类就可以完成id注入功能了。具体怎么做的呢?是用到了APT,APT全称Annotation Processing Tool
,也就是注解处理器。感兴趣的可以期待下我下篇文章。