为什么要使用注解
注解可以隐藏许多复杂代码的细节,提高代码的效率,注解在框架使用中是非常频繁的
自定义注解对于框架的构架有很大的作用
注解的基本格式
自定义注解的格式
//元注解 以及 @interface 所修饰的注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementTYPE.TYPE)
public @interface AnnotationName {
//注解属性
}
元注解
@Documented
@Documented
表示参与javadoc文档的生成
@Retention
这里注意注释和注解的区别
该注释会提示java检查被自定义注解修饰的类的代码格式是否符合注解要求的规范
@Retention(RetentionPolicy.SOURCE)
表示该注解不会参与类加载阶段,也不会在.class文件中生成
@Retention(RetentionPolicy.CLASS)
表示该注解会参与类加载阶段并存在于.class字节码文件中,但不会窜与运行阶段
@Retention(RetentionPolicy.RUNTIME)
表示该注解会参与运行阶段
@Target
@Target(ElementType.???)
决定当前注解可以作用于 Java 代码中那一部分内容,
通过枚举 ElementType 来决定当前注解可以使用范围
@Target可以作用的范围
ElementType.TYPE | 表示当前注解可以用于类和接口,以及枚举 |
ElementType.FIELD | 表示当前注解可以用于成员变量 |
ElementType.METHOD | 表示当前注解可以用于成员方法 |
ElementType.PARAMETER | 表示当前注解可以用于成员方法参数 @NotNull |
ElementType.CONSTRUCTOR | 表示当前注解可以用于构造方法 |
ElementType.ANNOTATION_TYPE | 表示当前注解可以用于注解 |
ElementType.LOCAL_VARIABLE | 表示当前注解可以用于局部变量 |
ElementType.PACKAGE | 表示当前注解可以用于包 |
当然,也可以定义一个注解用于多种类型之上,这时候就可以重写@Target注解,将注解的属性定义为ElementType类型的数组
public @interface Target {
ElementType[] value(); //ElementType为枚举类型
}
import static java.lang.annotation.ElementType.*;
// 表示当前注解可以用于类和接口,以及枚举,成员变量,成员方法,构造方法,参数列表,注解,局部变量里,包
@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, PARAMETER, ANNOTATION_TYPE,LOCAL_VARIABLE, PACKAGE})
// 表示当前注解可以用于属性
@Target({FIELD})
注解的属性
自定义注解时,可以在注解中定义属性,但是注解的属性有一个特殊点是【长了一张接口中缺省方法的脸】
例如
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestAnnotation01 {
int value();
String name();
TestEnum status();
TestAnnotation02[] TestAnnotations();
}
在这里我们可以看到注解中属性的类型可以是
基本数据类型,字符串类型,枚举类型,其他注解类型,以上类型的数组
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface TestAnnotation02 {
int value() default 0;
String name() default "小皮";
}
同时在设置注解属性时可以设置默认值
注解属性获取
拿上面的 TestAnnotation01 举例
@TestAnnotation01(value = 1,
name = "3mz",
status = TestEnum.LIFE,
TestAnnotations = {
@TestAnnotation02(value = 2, name = "百弟"),
@TestAnnotation02(name = "Roieeeee", value =3)})
public class Demo {
public static void main(String[] args) {
Class<Demo> cls = Demo.class;
//通过反射中的 getAnnotation 方法,获取注解属性的值
TestAnnotation01 annotation = cls.getAnnotation(TestAnnotation01.class);
System.out.println(annotation.value());
System.out.println(annotation.name());
System.out.println(annotation.status());
System.out.println(annotation.TestAnnotations()[0].name() + ":" + annotation.TestAnnotations()[0].value());
System.out.println(annotation.TestAnnotations()[1].name() + ":" + annotation.TestAnnotations()[1].value());
}
}