一、注解介绍
Java注解(Annotation)又称 Java 标注。Java 语言中的类、方法、变量、参数和包等都可以被标注。
1.1、注解写法
格式:
@Target 注解标注的目标:类、方法、变量、参数和包等
@Retention 作用域:源码、编译时、运行时
public @interface 注解名称{
属性列表;
}
注解通过 @interface 关键字进行定义,如下,定义一个MyAnnotation的注解:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
int value() default -1;
String name();
}
@Target、@Retention,也是元注解,元注解是可以注解到注解上的注解。
@Target
Target 目标,限定注解了标注的地方。取值如下:
- ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
- ElementType.CONSTRUCTOR 可以给构造方法进行注解
- ElementType.FIELD 可以给属性进行注解
- ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
- ElementType.METHOD 可以给方法进行注解
- ElementType.PACKAGE 可以给一个包进行注解
- ElementType.PARAMETER 可以给一个方法内的参数进行注解
- ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
@Target 可以给多个值,注解到多个地方,如
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
@Retention
Retention 英文意为保留,标识注解作用域,在什么时候有效。取值如下:
- RetentionPolicy.SOURCE 注解只在源码阶段保留,并被编译器忽略。
- RetentionPolicy.CLASS 注解在源码阶段、编译器进行编译时保留,它并不会被加载到 JVM 中。
- RetentionPolicy.RUNTIME 注解在源码阶段、编译器进行编译、运行时保留,运行时,它会被加载进入到 JVM 中,所以在程序运行时可以获取到它们。
SOURCE < CLASS < RUNTIME,即CLASS包含了SOURCE,RUNTIME包含SOURCE、CLASS。
@interface
定义注解时,用@interface定义
注解的属性
注解可以定义一些属性,如value、name:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
int value() default -1;
String name();
}
default 指定了默认值
1.2、注解的使用
我们定义一个注解,简单的使用,如下:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
int value() default -1;
}
//使用注解 MyAnnotation
public class MyAnnotationTest {
@MyAnnotation(value = 1)
private int age;
@MyAnnotation
private int age1;
......
}
Android元注解的使用
在Android中,系统源码帮我们定了一些元注解,如:IntDef, LongDef, StringDef,可以限定参数的取值范围,可以减少使用枚举,减少内存。
如,我们定义一个星期:
public static final int Sunday = 0;
public static final int Monday = 1;
public static final int Tuesday = 2;
public static final int Wednesday = 3;
public static final int Thursday = 4;
public static final int Friday = 5;
public static final int Saturday = 6;
再定义一个注解,限定使用这个注解时的取值,若不是限定的值,则源码就会报红:
@IntDef({Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday})
@Target({ElementType.PARAMETER, ElementType.FIELD})
@Retention(RetentionPolicy.SOURCE)
public @interface Week {
}
注解Week的使用:
@Week
private static int weekDay = Saturday;
public static void setWeekDay(@Week int weekDay){
AnnotationUsageDemo.weekDay = weekDay;
}
public static void main(String[] args) {
//报红,须使用:Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
//setWeekDay(5);
//正确
setWeekDay(Friday);
}
不使用限定值,报红,如图:
1.3、注解的用法
注解单独使用是没有意义的,常见的用法:
- 注解+开发工具(AS),用于源码期,做一些代码校验等,如注解:ResId、IntDef等
- 注解+APT 用于编译期时生成一些代码文件,如:butterknife、dagger2、hilt、databinding
- 注解+字节码操作 用于编译时字节码插桩,如:AspectJ、ARounter、CC
- 注解+反射 代码运行时,通过反射,进行相应的处理,如:XUtils、Lifecycle