文章目录
注解
注解(Annotation
) 为所有注释类型扩展的公共接口
元注解
@Retention
https://developer.android.com/reference/java/lang/annotation/Retention
定义了注解的生命周期,注解的生命周期有三个阶段:
第一阶段:注解只存在于java源文件,在编译成class文件时去掉注解。
第二阶段:注解存在于class文件,在将class文件转换成内存中的字节码的时候去掉注解。
第三阶段:注解存在于内存中的字节码。
@Retention(RetentionPolicy.SOURCE)
:注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里,即第一阶段。@Override
、@SuppressWarnings
都属于这类注解,可以做一些检查性的操作。
@Retention(RetentionPolicy.CLASS)
:注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机(JVM)中,即第二阶段。注解默认使用这种方式。
@Retention(RetentionPolicy.RUNTIME)
:源码、class文件和执行的时候都有注解的信息,VM将在运行期也保留注解信息,因此可以通过反射机制读取注解的信息,我们自定义的注解通常使用这种方式(划重点
),为第三阶段。@Deprecated
属于此类注解。
@Target
https://developer.android.com/reference/java/lang/annotation/Target
@Target
说明注解的作用目标,默认值为任何元素。取值有以下:
@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) //包
public enum ElementType {
TYPE,// Class, interface (including annotation type), or enum declaration
FIELD,// Field declaration (includes enum constants)
METHOD,// Method declaration
PARAMETER,// Formal parameter declaration
CONSTRUCTOR,// Constructor declaration
LOCAL_VARIABLE,// Local variable declaration
ANNOTATION_TYPE,// Annotation type declaration
PACKAGE,// Package declaration
/**
* @since 1.8
*/
TYPE_PARAMETER,// Type parameter declaration
/**
* @since 1.8
*/
TYPE_USE// Use of a type
}
@Inherited
https://developer.android.com/reference/java/lang/annotation/Inherited
@Inherited
说明子类可以继承父类中的该注解
@Documented
https://developer.android.com/reference/java/lang/annotation/Documented?hl=ru
@Documented
表明制作javadoc
时,是否将注解信息加入文档。如果注解在声明时使用了@Documented
,则在制作javadoc
时注解信息会加入javadoc
。
@Deprecated
https://developer.android.com/reference/java/lang/Deprecated
@Deprecated
意为“废弃的,过时的
”,也就是就是说这个方法已经废弃了,不建议使用,通常是因为它很危险,或者因为存在更好的替代方案。
@Override
https://developer.android.com/reference/java/lang/Override
@Override
意为“重写、覆盖
”,最常用的就是覆盖toString
public class OverrideTest {
@Override
public String toString() {
return super.toString();
}
}
编译器会自动检测,父类或超类有没有该方法toString
,如果没有,编译器就会报错。
@SuppressWarnings
@SuppressWarnings
意为“抑制警告
”,简单的说就是去掉编译器警告。
public class OverrideTest {
@SuppressWarnings("unchecked")
@Override
public String toString() {
return super.toString();
}
}
"unchecked
"用于去掉未经检查的警告。
自定义注解
注解的原理
在某个类上加一个注解,可以理解为相当于给这个类的class
加了一个Annotation
对象
isAnnotationPresent
检测指定注解类型的注解是否存在于此元素上,true
表示存在,false
表示不存在。
getAnnotation
返回此元素上指定注解类型的那个Annotation
对象。
自定义注解及其应用
自定义一个最简单的注解:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnotation {
}
@Retention
和@Target
在前面都有解释,把自定义的注解加到某个类上:
@MyAnnotation
public class AnnotionTest {
}
用反射测试AnnotionTest
的定义上是否有@MyAnnotation
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
if (AnnotionTest.class.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = AnnotionTest.class.getAnnotation(MyAnnotation.class);
Log.e(BuildConfig.TAG, "MyAnnotation:" + myAnnotation);
}
MyAnnotation
是一个类,这个类的实例对象myAnnotation
是通过反射得到的, 一旦在某个类上使用了@MyAnnotation
,那么这个MyAnnotation
类的实例对象myAnnotation
就会被创建出来了。
为注解增加属性
添加属性
语法:类型 属性名();
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnotation {
String color(); // 添加属性
}
-->// 应用属性
@MyAnnotation(color = "green")
public class AnnotionTest {
}
-->// 取得属性值
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
if (AnnotionTest.class.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = AnnotionTest.class.getAnnotation(MyAnnotation.class);
String color = myAnnotation.color(); // 输出green
为属性指定默认值
语法:类型 属性名() default 默认值;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnotation {
String color() default "blue";//为属性指定默认值
}
value属性
如果注解中有一个名称为value
的属性,且你只想设置value
属性(即其他属性都采用默认值或者你只有一个value
属性),那么可以省略掉“value=
”部分。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnotation {
String color() default "blue"; // 为属性指定默认值
String value(); // 定义一个名称为value的属性
}
-->// 应用属性
@MyAnnotation("abc") // value赋值为"abc"
public class AnnotionTest {
}
-->// 取得属性值
protected void onCreate(Bundle savedInstanceState) {
if (AnnotionTest.class.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = AnnotionTest.class.getAnnotation(MyAnnotation.class);
String color = myAnnotation.color();
String value = myAnnotation.value(); // "abc"
数组类型的属性
增加数组类型的属性:int[] arrayAttr() default {1,2,4};
应用数组类型的属性:@MyAnnotation(arrayAttr={2,4,5})
如果数组属性只有一个值,这时候属性值部分可以省略大括号,如:@MyAnnotation(arrayAttr=2)
,这就表示数组属性只有一个值,值为2
枚举类型的属性
增加枚举类型的属性:EumTrafficLamp lamp() default EumTrafficLamp.RED;
应用枚举类型的属性:@MyAnnotation(lamp=EumTrafficLamp.GREEN)
注解类型的属性
public @interface NewAnnotation {
String value();
}
为注解添加一个注解类型的属性,并指定注解属性的缺省值:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnotation {
NewAnnotation annotationAttr() default @NewAnnotation("xdp");
}
自定义注解综合示例
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface MyAnnotation {
String color() default "blue"; // 为属性指定默认值
String value(); // 定义一个名称为value的属性
int[] arrayAttr() default {1, 2, 4}; // 添加一个int类型数组的属性
ColorEnum lamp() default ColorEnum.RED; // 添加一个枚举类型的属性,并指定枚举属性的缺省值
NewAnnotation annotationAttr() default @NewAnnotation("xdp"); // 为注解添加一个注解类型的属性,并指定注解属性的缺省值
}
–> 应用属性
@MyAnnotation(color = "red",
value = "hgy413",
arrayAttr = {1, 4, 5},
lamp = ColorEnum.GREEN,
annotationAttr = @NewAnnotation("def"))
public class AnnotionTest {
}
–> // 取得属性值
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
if (AnnotionTest.class.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation myAnnotation = AnnotionTest.class.getAnnotation(MyAnnotation.class);
String color = myAnnotation.color(); // red
String value = myAnnotation.value(); // hgy413
int length = myAnnotation.arrayAttr().length; // 3
ColorEnum colorEnum = myAnnotation.lamp(); // ColorEnum.GREEN
String newValue = myAnnotation.annotationAttr().value(); // def