秒懂java注解,强烈推荐
apt实现butterknife框架,有些深度
apt方案的实践及其总结,很庞大,但是作者好像没有细化整理
在当前的开发过程中,很多框架都使用到apt这一技术,而apt的实现是基于java的注解生成的,比如:butterknife,retrofit,还有greendao等框架,此篇文章是基于别人的文章对java注解基础进行学习整理总结,对参考文章作者表示衷心感谢(特别是frank909,下面总结整理多是基于阁下文章,许多图片也是直接使用),此篇文章也多是自己个人理解,阅读者建议先学习上面的参考文章,再阅读文章比对,有不正确的地方欢迎指正交流。
- 学习java注解需要先了解下面几个实现:
- java注解的语法实现
- 注解的属性
- java注解元注解
- java,Android提供的系统注解
- java注解解析及其提取
- java注解的理解和使用
- 学习流程和上面不太一样,由于本人对注解了解甚少,所以先了解其实现,在实现的基础上再加深对其理解,感觉会理解的更深一些。
- java注解的语法实现:注解的声明和使用
- 注解的声明:和class,interface的声明类似,不同的是修饰符为@interface,即:
public @interface TestAnnotation {
}
- 注解的使用:注解的使用也很简单,使用@+注解类名即可,如果有属性则语法是@+注解类名+(),括号内是直接单个属性或者多属性的key=value类型。注解的使用范围:类,变量,方法,参数,构造方法,注解,注解属性等即:
@TestAnnotation
public class Test {
}
3.注解属性:注解和class一样可以声明变量值,在声明的同时还能够直接赋默认值,和class不同的是在注解类中不能声明带有方法体方法或者函数,而且注解属性的声明和class的变量声明也不一样,其声明类似于interface内部的接口api声明,返回值是其属性值的类型,方法名字是其属性的名字,默认值通过default这个关键字声明,即:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
public int id() default -1;
public String msg() default "Hi";
}
- 注解属性的使用,上面已经介绍,单属性在注解的括号内可以直接指定,多属性需要以key,value的形式在注解括号内指定。即:
@Check("hi")
int a;
@Check(value="hi")
int a;
- java提供的元注解及其系统提供的系统注解:
-元注解:和object类似,java系统提供了最基础的注解实现,同时也想语言学习的元音一样,其他发音都会基于这个音符发音,这几个注解都可以用于其他注解的自定义,元注解包含下面几个:
* @Retention:注解生命周期,或者说是存活期更准确一些,有下面三个值选择:
      * RetentionPolicy.SOURCE:存活到源码时期
      * RetentionPolicy.CLASS:存活到编译期,在代码
执行的时候声明的注解不能再被调用和使用
RetentionPolicy.RUNTIME:存活到运行期,在代码的执行时,还可以被使用。
      * 在代码的开发中,编译期和运行期是比较常用的时期
,源码期通常用于对源码的规范及其格式校验。
* @ Documented:文档注解,编辑代码文档使用比较多,代码开发中使用不多
* @ Target:目标注解,当前声明的注解作用于对象是谁,其值有类,方法,参数,变量,构造方法等。即:
ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
ElementType.CONSTRUCTOR 可以给构造方法进行注解
ElementType.FIELD 可以给属性进行注解
ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
ElementType.METHOD 可以给方法进行注解
ElementType.PACKAGE 可以给一个包进行注解
ElementType.PARAMETER 可以给一个方法内的参数进行注解
ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
* @ Inherited:继承传递注解,在class类的继承关系中,只要有一个类继承了注解,其所有的子类,孙子类都会继承这个注解。
* @ Repeatable:java1.8新添一个注解类型,重复注解:
* 容器注解,和对象的数组,list相似,容器注解就是某个注解的集合,即声明的注解中属性是另一个注解数组,即下面person是一个注解,persons也是一个注解,不同的是其持有一个注解集合即person的数组集合:
@interface Persons {
Person[] value();
}
@Repeatable(Persons.class)
@interface Person{
String role default "";
}
* 对于容器注解和重复注解理解不好,只能后续的开发学习中深化再来整理。
- java,Android提供的系统注解
- @Deprecated:废弃注解,Android也在使用,在历代的Android系统 更新中都有大批量的api被废弃不再使用,废弃的api都是使用这个注解标注。
- @Override: 子类重写父类api方法需要添加的一个注解,重写注解
- @SuppressWarnings:阻止警告注解,在java代码的开发中,不符合java规范的代码中会提示警告,加上这个注解不再对齐进行警告。
- @JavascriptInterface:js接口api注解,在Android的后续版本中在web页面中调用nativeapi方法需要加上这个注解,不然不能够被调用。
- @StringDef:字符串默认值注解,内部持有string数组,仅能用于其他注解的声明,不能直接用于参数,使用其可以声明一个作用于参数的注解控制参数的值只能使用提供的默认值。
- 后续会不断的整理用到和见识到的系统注解类型
- 注解的解析,提取(如何提取一个类中类,方法,参数上的注解)
- 自定义注解很简单,使用关键字@interface声明即可,使用也很简单,针对注解声明的使用范围进行标注即可,可是如何提取到类使用了那些注解呢?这个很重要的,在框架retrofit,rxjava的使用过程中都涉及到相应的注解的提取。注解的提取和java中另一个常用的技术反射又息息相关,类,方法,参数的注解提取依赖于java中类,方法,参数的反射,并使用系统提供的下面两个api获取其注解列表(单个注解)即可,即:
//校验对象是否包含注解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
{}
//获取单个注解
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}
//获取注解列表
public Annotation[] getAnnotations() {}
- 具体类的注解提取及其方法api的注解提取可以参考上面大神的文章,大神文章中没有对类进行反射,而是直接使用类名,涉及到类的反射可以参考响应的文章(包括我的其他后续文章)。
- 注解的理解:通过上面的描述,我的理解是注解是解释说明的作用,同时也可以看做是一篇文章的核心提纲,用一个简短的词或者简短的一句话对某个类,方法,参数字段甚至一段逻辑代码进行解释声明,只不过这个单词或者一句话带有语法规范。
- 注解的使用:涉及到注解的使用只能说是我当前的使用场景进行整理,其他可能还有很多场景使用:
- 通过系统注解声明新的注解对对象类,api方法,参数等进行控制,@stringdes的使用
- 通过注解及其属性声明对象核心逻辑及其核心参数等,比如retrofit对okhttp的接口的访问及其访问参数的声明
- 通过注解(apt)实现编译期代码的自动生成及其注入,当前很多框架都在使用,比如:butterknife,dagger2,greendao等
- 注解作为配置参数串联系统后台的对接,后端使用比较多,前端使用不是很多
- 后续以butterknife,dagger2两个框架更深入的学习注解及其apt注入
网友评论