文章目录

      • 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 SDK Document 框架导读的翻译和注解[1]
  2. Android快速调试方法
  3. Android Native 绘图方法
  4. Android 虚化图片的方法
  5. android完全退出程序的方法
  6. android常用方法汇总-更新中

随机推荐

  1. SQL查询结果区分大小写
  2. 关于淘宝的数据库系统
  3. 如何将空值传递给外键字段?
  4. python3.x的torndb使用记录(发现网上没有
  5. mysql日志文件过大导致磁盘空间不够的问
  6. 正确使用MySQL JDBC setFetchSize()方法
  7. 使用IP地址方法登录MySQL数据库Can&#39;t
  8. 是否可以从另一个sql脚本中的存储过程调
  9. 使用where的Laravel集合只在本地工作,而不
  10. 一个RESTful+MySQL程序