Android(安卓)注解基本使用
16lz
2021-12-04
文章目录
- Android注解基本使用
- 内置注解
- @Retention
- @Target
- Java自定义注解
- Android中注解替代枚举/常量
Android注解基本使用
注解(Annotation),是源码中特殊的语法元数据,类、方法、变量、参数都可以被注解。利用注解可以标记源码以便编译器为源码生成文档和检查代码,也可以让编译器和注解处理器在编译时根据注解自动生成代码,甚至可以保留到运行时以便改变运行时的行为。
内置注解
- @Override 注解用来表明该方法是重写父类方法,编译器会负责检查该方法与父类方法的声明是否一致。
- @Deprecated 注解用来表明该元素已经被废弃不建议使用了。
- @SuppressWarnings 注解用来表示编译器可以忽略特定警告。
@Retention
注解的保留位置:
- RetentionPolicy.SOURCE:源码阅读时使用,注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃。
- RetentionPolicy.CLASS:编译时使用,注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期。
- RetentionPolicy.RUNTIME:运行时使用,注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在。
这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码
@Target
注解作用目标:
- ElementType.TYPE:类、接口、枚举
- ElementType.FIELD:属性
- ElementType.METHOD:类中的方法
- ElementType.PARAMETER:方法参数
- ElementType.CONSTRUCTOR:构造器
- ElementType.LOCAL_VARIABLE:局部变量
- ElementType.ANNOTATION_TYPE:注解
- 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);
更多相关文章
- Android(安卓)Native 绘图方法
- Invalidate和postInvalidate的区别
- Android(安卓)AsyncTask完全解析
- Android消息机制
- 利用HTML5开发Android笔记(中篇)
- 【译】Google官方推出的Android架构组件系列文章(六)Room持久化库
- Android工程中R.java文件的重新生成——注意资源文件的错误
- 【Android】动态链接库so的加载原理
- 抛开android获取app的签名 —— 一次源码探索之旅