前言
注解(Annotation),是源码中特殊的语法元数据,类、方法、变量、参数都可以被注解。利用注解可以标记源码以便编译器为源码生成文档和检查代码,也可以让编译器和注解处理器在编译时根据注解自动生成代码,甚至可以保留到运行时以便改变运行时的行为。
内置注解
- @Override 注解用来表明该方法是重写父类方法,编译器会负责检查该方法与父类方法的声明是否一致。
- @Deprecated 注解用来表明该元素已经被废弃不建议使用了。
- @SuppressWarnings 注解用来表示编译器可以忽略特定警告。
注解类型的声明
注解类型的声明和接口的声明类似,不过需要使用 @interface 和元注解(用来定义注解的注解)描述,每个方法声明定义了注解类型的一个元素,且方法声明不能包含任何参数或 throws,方法的返回类型必须是原语类型、String、Class、枚举、注解和这些类型的数组,方法可以有默认值,如:
public @interface RequestForEnhancement{
int id();
String synopsis(); //概要
String enginner() default "[unassigned]";
String date() default"[unimplemented]";
}
定义完注解类型后,就可以用它去注解一些声明了。注解是一种特殊的修饰符,可以像 public、static 或 final 修饰符一样使用,不过通常注解要写在这些修饰符之前。使用时为 @ 符号加注解类型加元素值对列表并用括号括起来,如:
@RequestForEnhancement(
id=123456,
synopsis = "This is SYNOPSIS",
enginner = "Zc",
date = "2018/04/20"
)
public void message(){
}
如果一个注解中没有方法和元素,那么被称为标记注解类型
@Request
public void message(){
}
public @interface Request {
}
如果注解类型只有一个元素,那么元素应该命名为 value,使用时也就可以忽略元素名和等号了,如:
public @interface OnlyOne {
String value();
}
除此之外,还有一些注解需要用元注解去描述:
@Documented //表明该注解类型可以被 javadoc 等工具文档化
//表明该注解类型可以保留多长时间,值为枚举值 RetentionPolicy:
@Retention(RetentionPolicy.CLASS)//会被编译记录在class文件中,默认的行为,不需要被VM保留到运行时
@Retention(RetentionPolicy.SOURCE)//只保留在源码中,会被编译器丢弃
@Retention(RetentionPolicy.RUNTIME)//被编译器记录在class文件中,并被VM保留到运行时,所以可以通过反射获取
//表明该注解类型可以注解哪些程序元素,如果不适用@Target描述
//默认可以注解所有的程序元素。值是枚举数组 ElementType[]:
@Target(ElementType.TYPE)//类、接口(包括注解类型)、枚举的声明
@Target(ElementType.FIELD)//字段(包括枚举常量)的声明
@Target(ElementType.METHOD)//方法的声明
@Target(ElementType.PARAMETER)//形参的声明
@Target(ElementType.CONSTRUCTOR)//构造器构造函数的声明
@Target(ElementType.LOCAL_VARIABLE)//本地变量的声明
@Target(ElementType.ANNOTATION_TYPE)//注解类型的声明
@Target(ElementType.PACKAGE)//包的声明
@Target(ElementType.TYPE_PARAMETER)//泛型参数的声明
@Target(ElementType.TYPE_USE)//泛型的使用
//表明该注解类型将被自动继承。也就是说,如果注解类型被 @Inherited 注解,
//此时用户查询一个类声明的注解,而类声明没被该注解类型注解
//那么将自动查询该类父类的注解类型,以此类推直到找到该注解类型或达到顶层 Object 对象。
@Inherited
public @interface OnlyOne {
}
安卓源码中的注解
- @UiThread、@WorkerThread 注解进行线程检查
- @NonNull 注解进行空检查
- @IdRes 表明这个整数代表资源引用
- @IntDef、@StringDef 注解自定义注解来代替枚举,如描述应用中使用的字体文件
注解的使用和通过反射回去注解
首先写一个注解的声明
@Documented
@Retention(RetentionPolicy.RUNTIME)//运行时注解,可以通过反射来获取
@Target(ElementType.METHOD)//方法的声明
public @interface UserAnnotation {
String name() default "My name is 666";
String date();
int age() default 100;
}
调用以及反射获取这个注解:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Class cls=Class.forName("com.zci.demo.android8.MainActivity");
for (Method method:cls.getMethods()){
UserAnnotation userAnnotation=
method.getAnnotation(UserAnnotation.class);
if (userAnnotation!=null){
Log.e("UserAnnotation",userAnnotation.name());
Log.e("UserAnnotation",userAnnotation.date());
Log.e("UserAnnotation",userAnnotation.age()+"");
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* 使用一个注解
* @return
*/
@UserAnnotation(
name = "Zc",
date = "2018/04/20")
public String getMessage() {
return "我爱北京天安门,天安门上太阳升";
}
=
}