@@ -15,7 +15,9 @@ RxJava详解
1515###说明
1616- ` Annotation ` 的声明是通过关键字` @interface ` 。这个关键字会去继承` Annotation ` 接口。
1717- ` Annotation ` 的方法定义是独特的、受限制的。
18- ` Annotation ` 类型的方法必须声明为无参数、无异常的。这些方法定义了` Annotation ` 的成员: 方法名代表成员变量名,而方法返回值代表了成员变量的类型。而且方法的返回值类型必须是基本数据类型、` Class ` 类型、枚举类型、` Annotation ` 类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用` default ` 和一个默认的数值来声明成员变量的默认值,` null ` 不能作为成员变量的默认值,这与我们平时的使用有很大的区别。
18+ ` Annotation ` 类型的方法必须声明为无参数、无异常的。这些方法定义了` Annotation ` 的成员: 方法名代表成员变量名,而方法返回值代表了成员变量的类型。而且方法的返回值类型必须是基本数据类型、` Class ` 类型、枚举类型、` Annotation ` 类型或者由前面类型之一作为元素的一维数组。方法的后面可以使用` default ` 和一个默认的数值来声明成员变量的默认值,` null ` 不能作为成员变量的默认值,这与我们平时的使用有很大的区别。
19+ 注解如果只有一个默认属性,可直接用` value() ` 函数。一个属性也没有则表示该` Annotation ` 为` Mark Annotation ` 。
20+
1921
2022例如:
2123``` java
@@ -31,6 +33,12 @@ public @interface UseCase {
3133
3234` Annotation ` 一般作为一种辅助途径,应用在软件框架或者工具中。让这些工具类可以根据不同的` Annotation ` 注解信息来采取不同的处理过程或者改变相应程的行为。
3335
36+ 具体可分为如下三类:
37+
38+ - 标记,用于告诉编译器一些信息
39+ - 编译时动态处理,如动态生成代码
40+ - 运行时动态处理,如得到注解信息
41+
3442
3543###Annotation分类
3644
@@ -54,17 +62,166 @@ public @interface UseCase {
5462元` Annotation ` 是指用来定义` Annotation ` 的` Annotation ` 。
5563
5664- `@Retention
65+ 保留时间,可为` RetentionPolicy.SOURCE(源码时) ` 、` RetentionPolicy.CLASS(编译时) ` 、` RetentionPolicy.RUNTIME(运行时) ` ,默认为` CLASS ` 。如果值为` RetentionPolicy.SOURCE ` 那大多都是` Mark Annotation ` ,例如:` Override ` 、` Deprecated ` 、` Suppress Warnings ` 。` SOURCE ` 表示仅存在于源码中,在` class ` 文件中不会包含。` CLASS ` 表示会在` class ` 文件中存在,但是运行时无法获取。` RUNTIME ` 表示会在` class ` 文件中存在,并且在运行时可以通过反射获取。
5766
5867- ` @Target `
59-
68+ 用来标记可进行修饰哪些元素,例如 ` ElementType.TYPE ` 、 ` ElementType.METHOD ` 、 ` ElementType.CONSTRUCTOR ` 、 ` ElementType.FIELD ` 、 ` ElementType.PARAMETER ` 等,如果未指定则默认为可修饰所有。
6069- ` @Inherited `
61-
70+ 子类是否可以继承父类中的该注解。
6271- ` @Documented `
72+ 是否会保存到` javadoc ` 文档中。
73+
74+ ###自定义` Annotation `
75+
76+
77+
78+ ###` Annotation ` 解析
79+
80+
81+ 当Java源代码被编译时,编译器的一个插件annotation处理器则会处理这些annotation。处理器可以产生报告信息,或者创建附加的Java源文件或资源。如果annotation本身被加上了RententionPolicy的运行时类,则Java编译器则会将annotation的元数据存储到class文件中。然后,Java虚拟机或其他的程序可以查找这些元数据并做相应的处理。
82+
83+ 当然除了annotation处理器可以处理annotation外,我们也可以使用反射自己来处理annotation。Java SE 5有一个名为AnnotatedElement的接口,Java的反射对象类Class,Constructor,Field,Method以及Package都实现了这个接口。这个接口用来表示当前运行在Java虚拟机中的被加上了annotation的程序元素。通过这个接口可以使用反射读取annotation。AnnotatedElement接口可以访问被加上RUNTIME标记的annotation,相应的方法有getAnnotation,getAnnotations,isAnnotationPresent。由于Annotation类型被编译和存储在二进制文件中就像class一样,所以可以像查询普通的Java对象一样查询这些方法返回的Annotation。
84+
85+
86+ #####运行时` Annotation ` 解析
87+ 该类是指` @Retention ` 为` RUNTIME ` 的` Annotation ` 。
88+ 该类型的解析其实本质的使用反射。反射执行的效率是很低的
89+ 如果不是必要,应当尽量减少反射的使用,因为它会大大拖累你应用的执行效率。
90+
91+ 例如` Target ` 为` Method ` 的注解就可以通过` Method ` 中的如下方法进行解析:
92+
93+ ``` java
94+
95+ public < A extends Annotation > A getAnnotation(Class<A > annotationType) {
96+ ...
97+ }
98+
99+ public Annotation [] getAnnotations() {
100+ ...
101+ }
102+
103+ public boolean isAnnotationPresent(Class<? extends Annotation > annotationType) {
104+ ...
105+ }
106+ ```
107+
108+ 当然如果` Target ` 为` Field ` 、` Class ` 等那就要去使用` Filed ` 或` Class ` 中的方法来解析了。
109+ ``` java
110+ public static void main(String [] args) {
111+ try {
112+ Class cls = Class . forName(" cn.trinea.java.test.annotation.App" );
113+ for (Method method : cls. getMethods()) {
114+ MethodInfo methodInfo = method. getAnnotation(
115+ MethodInfo . class);
116+ if (methodInfo != null ) {
117+ System . out. println(" method name:" + method. getName());
118+ System . out. println(" method author:" + methodInfo. author());
119+ System . out. println(" method version:" + methodInfo. version());
120+ System . out. println(" method date:" + methodInfo. date());
121+ }
122+ }
123+ } catch (ClassNotFoundException e) {
124+ e. printStackTrace();
125+ }
126+ }
127+ ```
63128
64- #####自定义` Annotation `
65129
66130
67131
132+ #####编译时` Annotation ` 解析
133+
134+ 该类值` @Retention ` 为` CLASS ` 的` Annotation ` ,由` APT(Annotaion Processing Tool) ` 自动进行解析。是在编译时注入,所以不会像反射一样影响效率问题。
135+
136+ 我们需要做的是:
137+
138+ - 自定义类继承` AbstractProcessor `
139+ - 重写` process ` 方法
140+
141+ 例如:
142+
143+ ``` java
144+ @SupportedAnnotationTypes ({ " cn.trinea.java.test.annotation.MethodInfo" })
145+ public class MethodInfoProcessor extends AbstractProcessor {
146+
147+ @Override
148+ public boolean process (Set<? extends TypeElement > annotations , RoundEnvironment env ) {
149+ HashMap<String , String > map = new HashMap<String , String > ();
150+ for (TypeElement te : annotations) {
151+ for (Element element : env. getElementsAnnotatedWith(te)) {
152+ MethodInfo methodInfo = element. getAnnotation(MethodInfo . class);
153+ map. put(element. getEnclosingElement(). toString(), methodInfo. author());
154+ }
155+ }
156+ return false ;
157+ }
158+ }
159+ ```
160+ SupportedAnnotationTypes 表示这个 Processor 要处理的 Annotation 名字。
161+ process 函数中参数 annotations 表示待处理的 Annotations,参数 env 表示当前或是之前的运行环境
162+ process 函数返回值表示这组 annotations 是否被这个 Processor 接受,如果接受后续子的 rocessor 不会再对这个 Annotations 进行处理
163+
164+
165+
166+ ###使用注解提高代码的检查性
167+
168+ ` Google ` 提供了` Support-Annotations library ` 来支持更多的注解功能。
169+ 可以直接在` build.gradle ` 中添加如下代码:
170+
171+ ```
172+ dependencies {
173+ compile 'com.android.support:support-annotations:23.3.0'
174+ }
175+ ```
176+
177+ ` Android ` 提供了很多注解来支持在方法、参数和返回值上面使用,例如:
178+
179+ - ` @Nullable `
180+ 可以为` null `
181+
182+ - ` @NonNull `
183+ 不能为` null `
184+ - ` @StringRes `
185+ ` R.string ` 类型的资源。
186+ - ` @DrawableRes `
187+ ` Drawable ` 类型的资源。
188+ - ` @ColorRes `
189+ ` Color ` 类型的资源。
190+ - ` @InterpolatorRes `
191+ ` Interpolatro ` 类型。
192+ - ` @AnyRes `
193+ ` R. ` 类型。
194+ - ` @UiThread `
195+ 从` UI thread ` 调用。
196+ - ` @RequiresPermission `
197+ 来验证该方法的调用者所需要有的权限。检查一个列表中的任何一个权限可以使用` anyOf ` 属性。想要检查一个权限集合
198+
199+
200+ 例如:
201+
202+ ``` java
203+ import android.support.annotation.NonNull ;
204+ ...
205+
206+ /* * Add support for inflating the <fragment> tag. */
207+ @NonNull
208+ @Override
209+ public View onCreateView(String name, @NonNull Context context,
210+ @NonNull AttributeSet attrs) {
211+ ...
212+ }
213+ ...
214+ ```
215+
216+ ``` java
217+ import android.support.annotation.StringRes ;
218+ ...
219+ public abstract void setTitle(@StringRes int resId);
220+ ...
221+
222+ 遇到那种你写了个`setTitle(int resId)`他确给你传`setTitle(R . drawable. xxx)`的选手,用这种方式能很好的去提示下。
223+ ```
224+
68225
69226---
70227
0 commit comments