Android

注解基础

#Android

注解基础

本文主要是介绍注解的基础知识,为后面的APT和JavaPoet打下基础

0x01 什么是注解

注解(Annotation)是Java5的一个新特性,是插入在代码中的一种注释或者说是一种元数据(meta data),这些注释信息可以在编译期使用预编译工具进行获取处理,也可以在运行期使用Java反射机制来获取,这取决于你的注解类型。

0x02 注解的语法及其定义

在Android中注解经常存在我们代码中:

@Override  
protected void onCreate(Bundle savedInstanceState) {  
 super.onCreate(savedInstanceState);  
 setContentView(R.layout.activity_main4);  
 getIntentData();  
}  

上面的@Override就是系统的注解,表明这是个重写方法,点击源码可以看到长成下面的样子

@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.SOURCE)  
public @interface Override {  
}  

实际中会带有一些参数

@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.METHOD)  
public @interface run_methodInfo {  
 String name() default "long";  
 String data();  
 int id() default 365;  
}  

@Retention @Target @Document @Inherited四种 是元注解即 “注解的注解”

@Target 表示该注解目标,可能的 ElemenetType 参数包括:

  • ElemenetType.CONSTRUCTOR 构造器声明
  • ElemenetType.FIELD 域声明(包括 enum 实例)
  • ElemenetType.LOCAL_VARIABLE 局部变量声明
  • ElemenetType.METHOD 方法声明
  • ElemenetType.PACKAGE 包声明
  • ElemenetType.PARAMETER 参数声明
  • ElemenetType.TYPE 类,接口(包括注解类型)或enum声明

@Retention 表示该注解的生命周期,可选的 RetentionPolicy 参数包括

  • RetentionPolicy.SOURCE 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃注解将被编译器丢弃
  • RetentionPolicy.CLASS 注解被保留到class文件,但jvm加载class文件时候被遗弃
  • RetentionPolicy.RUNTIME 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;,因此可以通过反射机制读取注解的信息

@Documented 指示将此注解包含在 javadoc 中
@Inherited 指示允许子类继承父类中的注解

使用注解需要遵守它的规则:

  • Annotation型定义为@interface, 所有的Annotation会自动继承java.lang.Annotation这一接口,并且不能再去继承别的类或是接口.
  • 参数成员只能用public或默认(default)这两个访问权修饰
  • 参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String、Enum、Class、annotations等数据类型,以及这一些类型的数组.
  • 要获取类方法和字段的注解信息,必须通过Java的反射技术来获取 Annotation对象,因为你除此之外没有别的获取注解对象的方法(分为编译期还是运行期)

0x03 使用

(这里仅介绍最常见的运行期的注解,编译期注解涉及到apt、javapoet会单独再开一篇介绍)

Step One 定义注解

先看三个Runtime注解,包括类、方法、字段,

@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.TYPE)  
public @interface run_classInfo {  
 String value();  
}  
  
@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.METHOD)  
public @interface run_methodInfo {  
 String name() default "long";  
 String data();  
 int id() default 365;  
}  

@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.FIELD)  
public @interface run_fieldInfo {  
 int\[\] value();  
}  

Step two 使用这些注解

@run_classInfo("类注解RunTime Class")  
public class RunTimeTest {  
 @run_fieldInfo(value = {77, 88})  
 public String fieldInfo = "filedInfo";  
  
 @run_fieldInfo(value = {163})  
 public int id = 55;  
  
 @run_methodInfo(name = "彩笔学长", data = "finance")  
 public static String getMethod() {  
 return RunTimeTest.class.getSimpleName();  
 }  
}  

使用反射解析注解


/**  
 * 解析运行时注解  
 */  
private void showRunTimeInfo() {  
 StringBuffer sb = new StringBuffer();  
 //获取Class 注解  
 Class<?> clazz = RunTimeTest.class;  
 Constructor<?>\[\] constructors = clazz.getConstructors();  
 //获取包含的注解类信息  
 run\_classInfo runClassInfo = clazz.getAnnotation(run\_classInfo.class);  
 if (runClassInfo != null) {  
 //获取class注解  
 sb.append("Class注解: ").append("\\n");  
 sb.append(Modifier.toString(clazz.getModifiers())).append(" ")  
 .append(clazz.getSimpleName()).append("\\n");  
  
 sb.append("注解值:").append("\\n")  
 .append(runClassInfo.value()).append("\\n\\n");  
 }  
  
 //获取Field注解  
 sb.append("Field注解:").append("\\n");  
 Field\[\] fields = clazz.getDeclaredFields(); //获取自身的不包括继承类  
 for (Field field : fields) {  
 //获取field注解类信息  
 run\_fieldInfo fieldInfo = field.getAnnotation(run\_fieldInfo.class);  
 if (fieldInfo != null) {  
 sb.append(Modifier.toString(field.getModifiers())).append(" ")  
 .append(field.getType().getSimpleName()).append(" ")  
 .append(field.getName()).append("\\n");  
 sb.append("注解值: ").append("\\n")  
 .append(Arrays.toString(fieldInfo.value())).append("\\n\\n");  
 }  
 }  
  
 //获取Method 注解  
 sb.append("Method注解: ").append("\\n");  
 Method\[\] methods = clazz.getDeclaredMethods();  
 for (Method method : methods) {  
 run\_methodInfo methodInfo = method.getAnnotation(run\_methodInfo.class);  
 if (methodInfo != null) {  
 sb.append(Modifier.toString(method.getModifiers())).append(" ")  
 .append(method.getReturnType().getSimpleName()).append(" ")  
 .append(method.getName()).append("\\n");  
 sb.append("注解值:").append("\\n");  
 sb.append("name: ").append(methodInfo.name()).append("\\n");  
 sb.append("data: ").append(methodInfo.data()).append("\\n");  
 sb.append("id: ").append(methodInfo.id()).append("\\n");  
 }  
  
 }  
 tvDes.setText(sb.toString());  
} 

##0x04 参考文献