Android注解篇-各类型注解的意义以及使用场景

前言

注解(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 "我爱北京天安门,天安门上太阳升";
    }
=
}

猜你喜欢

转载自blog.csdn.net/Panda_Program/article/details/80018323