文章目录

      • Android注解基本使用
          • 内置注解
          • @Retention
          • @Target
        • Java自定义注解
        • Android中注解替代枚举/常量

Android注解基本使用

注解(Annotation),是源码中特殊的语法元数据,类、方法、变量、参数都可以被注解。利用注解可以标记源码以便编译器为源码生成文档和检查代码,也可以让编译器和注解处理器在编译时根据注解自动生成代码,甚至可以保留到运行时以便改变运行时的行为。

内置注解
  • @Override 注解用来表明该方法是重写父类方法,编译器会负责检查该方法与父类方法的声明是否一致。
  • @Deprecated 注解用来表明该元素已经被废弃不建议使用了。
  • @SuppressWarnings 注解用来表示编译器可以忽略特定警告。
@Retention

注解的保留位置:

  1. RetentionPolicy.SOURCE:源码阅读时使用,注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃。
  2. RetentionPolicy.CLASS:编译时使用,注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期。
  3. RetentionPolicy.RUNTIME:运行时使用,注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在。

这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码

@Target

注解作用目标:

  1. ElementType.TYPE:类、接口、枚举
  2. ElementType.FIELD:属性
  3. ElementType.METHOD:类中的方法
  4. ElementType.PARAMETER:方法参数
  5. ElementType.CONSTRUCTOR:构造器
  6. ElementType.LOCAL_VARIABLE:局部变量
  7. ElementType.ANNOTATION_TYPE:注解
  8. ElementType.PACKAGE:包

Java自定义注解

自定义注解:

/** * 定义类注解 */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface ClassInfo {    String value();}/** * 定义字段注解 */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface FieldInfo {    int[] value();}/** * 定义方法注解 */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public @interface MethodInfo {    String name() default "默認值";    String data();    int age() default 100;}/** * 使用注解 */@ClassInfo("测试类")public class TestAnnotation {    @FieldInfo(value = {1, 2})    public String fieldA = "字段属性";    @FieldInfo(value = {100})    public int fieldB = 100;    @MethodInfo(name = "这是一个方法名字", data = "hello")    public static String getMethodA() {        return TestAnnotation.class.getSimpleName();    }    @MethodInfo(data = "hello2")    public static String getMethodB() {        return TestAnnotation.class.getSimpleName();    }}

运行注解:

public class Test {    public static void main(String[] args) {        Class<TestAnnotation> cls = TestAnnotation.class;        ClassInfo classInfo = cls.getAnnotation(ClassInfo.class);        if (classInfo != null) {            System.out.println(cls);            System.out.println(classInfo);            System.out.println(classInfo.value());        }        System.out.println("---------------------");        Field[] fields = cls.getDeclaredFields();        for (Field field : fields) {            FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class);            if (fieldInfo != null) {                System.out.println(field);                System.out.println(fieldInfo);                System.out.println(Arrays.toString(fieldInfo.value()));            }        }        System.out.println("---------------------");        Method[] methods = cls.getDeclaredMethods();        for (Method method : methods) {            MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);            if (methodInfo != null) {                System.out.println(method);                System.out.println(methodInfo);                System.out.println(methodInfo.name());                System.out.println(methodInfo.data());                System.out.println(methodInfo.age());            }        }    }}

输出信息:

class com.immersionstatusbar.test.TestAnnotation@com.immersionstatusbar.test.ClassInfo(value=测试类)测试类---------------------public java.lang.String com.immersionstatusbar.test.TestAnnotation.fieldA@com.immersionstatusbar.test.FieldInfo(value=[1, 2])[1, 2]public int com.immersionstatusbar.test.TestAnnotation.fieldB@com.immersionstatusbar.test.FieldInfo(value=[100])[100]---------------------public static java.lang.String com.immersionstatusbar.test.TestAnnotation.getMethodA()@com.immersionstatusbar.test.MethodInfo(name=这是一个方法名字, age=100, data=hello)这是一个方法名字hello100public static java.lang.String com.immersionstatusbar.test.TestAnnotation.getMethodB()@com.immersionstatusbar.test.MethodInfo(name=默認值, age=100, data=hello2)默認值hello2100

Android中注解替代枚举/常量

通常定义固定值可以直接使用枚举或static final定义常量。

  • 使用枚举缺点比较消耗资源,优点是可以限制取值范围;
  • 使用常量优点是相对轻量级,确实不能限制取值范围。
// 枚举public enum TYPE_ENUM {    TYPE_A,    TYPE_B,    TYPE_C}// 常量public class TYPE_CONSTANT {    public static final int TYPE_A = 1;    public static final int TYPE_B = 2;    public static final int TYPE_C = 3;}// 定义变量// 取值只能为{TYPE_A,TYPE_B,TYPE_C}TYPE_ENUM enumVar;// 取值不受限制int type;

为了解决上面的这些问题,Android提供一个有用的注解,简化枚举和常量

implementation 'com.android.support:support-annotations:25.2.0'

如:@IntDef@StringDef

public class Person {    public static final int TYPE_A = 1;//男    public static final int TYPE_B = 2;//女    public static final int TYPE_C = 3;//保密    // 定义一个注解    @IntDef({TYPE_A, TYPE_B, TYPE_C})    @interface Type {    }    //年齡限制:0-100    private int age;    //性別限制:男,女,保密    private int sex;    @Type    public int getSex() {        return sex;    }    public void setSex(@Type int sex) {        this.sex = sex;    }    public void setAge(@IntRange(from = 0, to = 100) int age) {        this.age = age;    }    @IntRange(from = 0, to = 100)    public int getAge() {        return age;    }}

使用:

Person person = new Person();person.setAge(18);person.setAge(Person.TYPE_A);

更多相关文章

  1. Android(安卓)Native 绘图方法
  2. Invalidate和postInvalidate的区别
  3. Android(安卓)AsyncTask完全解析
  4. Android消息机制
  5. 利用HTML5开发Android笔记(中篇)
  6. 【译】Google官方推出的Android架构组件系列文章(六)Room持久化库
  7. Android工程中R.java文件的重新生成——注意资源文件的错误
  8. 【Android】动态链接库so的加载原理
  9. 抛开android获取app的签名 —— 一次源码探索之旅

随机推荐

  1. 给VMware下的Linux扩展磁盘空间(以CentOS6
  2. linux 输入参数利用getopt、struct optio
  3. Linux内核黑客的虚拟环境
  4. Awk 命令学习总结、AWk命令系列学习(linux
  5. Linux Mint 18.1安装nvidia驱动
  6. Linux: xclip,pbcopy,xsel用法 terminal
  7. Linux 性能查看命令:
  8. 熟悉Linux系统的操作
  9. Ubuntu安装软件提示boot空间不足
  10. Linux2.6.6内核下ACPI PCI Hot-Plug的实