目录
1.注解的概述
注解顾名思义就是对代码的 注释 + 解释
注解:
1. 给当前程序的开发者提供必要的信息和标记
2. 给 Java 编译或者 JVM 提供必要数据支持和标记
注解的定义
Java注解它提供了一种安全的类似注释的机制,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。
Java注解是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用,起到说明、配置的功能。
2.注解的分类
2.1标准注解
@FunctionalInterface
声明失一个函数式接口注解,这个是 Java 1.8 版本引入的新特性。函数式编程很火,所以 Java 8 也及时添加了这个特性。
@FunctionalInterface
public interface Test1 {
void test();
}
函数式接口:
接口内有且只有一个没有方法体的方法的接口
@override
重载标记,用 @Override 标记一个实际上并没有覆写父类的方法时,java 编译器会报警告
public class Test2 implements Test1 {
@Override
public void test() {
System.out.println("test");
}
}
@Deprecated
这个元素是用来标记过时的元素,想必大家在日常开发中经常碰到。编译器在编译阶段遇到这个注解时会发出提醒警告,告诉开发者正在调用一个过时的元素比如过时的方法、过时的类、过时的成员变量。
@SuppressWarnings
警告压制,会压制代码报出的异常警告和错误警告。
deprecation 使用了不赞成使用的类或方法时的警告 unchecked 执行了未检查的转换时的警告,例如当使用集合时没有用泛型(Generics)来指定集合保存的类型 deprecation 使用了不赞成使用的类或方法时的警告 path 在类路径、源文件路径等中有不存在的路径时的警告 serial 当在可序列化的类上缺少serialVersionUID定义时的警告 finally 任何finally子句不能正常完成时的警告 fallthrough 当Switch程序块直接通往下一种情况而没有Break 时的警告 all 所有的警告
2.2 元注解
@Documented
标记当前注解参与 Javadoc 操作,可以生成对应的【JavaDOC 文档】
@Retention
@ Retention 用来定义该注解在哪一个级别可用,在源代码中(SOURCE)、类文件中(CLASS)或者运行时(RUNTIME)。
方法 | 功能概述 |
RetentionPolicy.SOURCE | 可以参与代码编译过程,提供相对于的标记,提示 Java 编译器在编程过程中,检查相对应的代码格式,是否满足当前的注解需求 |
RetentionPolicy.CLASS | 对应注解可以在 Class 文件中存在, 但是不会参与 程序运行,默认注解行为 |
RetentionPolicy.RUNTIME | 对应注解参与编译过程,生成的 .class 字节码文件,并且在程序运行过程中存在,可以利用【反射】操作获取对应的注解信息,从注解中得到相应的数据内容。 |
@Target
@Target 决定当前注解可以作用于 Java 代码中那一部分内容,通过枚举 ElementType 来决定当前注解可以使用范围
ElementType | 功能概述 |
---|---|
ElementType.TYPE | 表示当前注解可以用于类和接口,以及枚举 |
ElementType.FIELD | 表示当前注解可以用于成员变量 |
ElementType.METHOD | 表示当前注解可以用于成员方法 |
ElementType.PARAMETER | 表示当前注解可以用于成员方法参数 @NotNull |
ElementType.CONSTRUCTOR | 表示当前注解可以用于构造方法 |
ElementType.ANNOTATION_TYPE | 表示当前注解可以用于注解 |
ElementType.LOCAL_VARIABLE | 表示当前注解可以用于局部变量 |
ElementType.PACKAGE | 表示当前注解可以用于包 |
@Inherited
说明子类可以继承父类中的该注解。表示自动继承注解类型。 如果注解类型声明中存在 @Inherited 元注解,则注解所修饰类的所有子类都将会继承此注解。
@Repeatable
@Repeatable 表示注解可以重复使用。
2.3自定义注解
创建自定义注解
import java.lang.annotation.*;
//自定义注解
//设置元注解,参与代码运行,只能用在类或接口,枚举上
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
/**
* 当前注解属性名为Value
* @return 注解反馈的数据类型为String
*/
String value() default "";
/**
* 当前注解属性名为Name
* @return 注解反馈的数据类型为String
*/
String name() default "";
/**
* 当前注解属性名为status
* @return 注解反馈的数据类型为int
*/
int status() default 10;
/**
* 当前注解属性名为annotations
* @return 注解反馈的数据类型为自定义注解数组
*/
MyAnnotation1[] annotations() default {};
}
【注意】 1. 注解中如果需要使用属性,属性列表中必须有一个 value 反馈类型任意 2. 注解属性可以给予默认数据,如果在用户使用当前注解时,没有对指定属性 进行数据提供,当前注解属性反馈数据为默认数据
注解属性
【注意】
1.在注解中定义属性时它的类型必须是 8 种基本数据类型外加 类、接口、注解及它们的数组。
2.注解中任意属性没有使用 default 添加默认值,在使用注解的过程中
没有提供对应的数据情况下,直接【报错】
3. 注解使用过程中,没有明确赋值目标属性名称,对应的数据直接给 value 属性
自定义反射的使用
@MyAnnotation(
value = "CTRL",
name = "鸡哥",
status = 1,
orderStatus = MyEnum.ORDER_HAVE_PAID,
annotations = {
@MyAnnotation2(value = 16,name = "张三"),
@MyAnnotation2(value = 17,name = "李四")
}
)
public class Demo1 {
public static void main(String[] args) {
/*
用反射获取当前类对象
*/
Class<Demo1> cls = Demo1.class;
/*
通过Class对象获取指定注解类型注解对象
*/
MyAnnotation1 annotation = cls.getAnnotation(MyAnnotation1.class);
//反射获取的注解对象调用注解方法
System.out.println(annotation.value());
System.out.println(annotation.status());
System.out.println(annotation.name());
System.out.println(annotation.orderStatus());
System.out.println(annotation.annotations()[0].name() +":"+annotation.annotations()[0].value());
System.out.println(annotation.annotations()[1].name() +":"+annotation.annotations()[1].value());
}
}