1.注解简介
1.1 什么是注解
- 注解:Annotation,
@interface,是和class、inteface同一等级的代码说明。 - 是一种记号,记号本身没有功能,是其它软件、其它代码增加的功能。
- 可以这样理解注解:想像代码具有生命,注解就是对于代码中某些鲜活个体的贴上去的一张标签。简化来讲,注解如同一张标签。
💡注意:注解不同于注释。
- 注释是给开发人员看的,没有任何功能。
//,/**//***/- 注解是给框架/软件看的,可以由框架或者其它软件赋予注解一些功能
1.2 JDK的常见注解
-
编译检查:
@Override:被@Override标记的方法,idea/eclipse会提供功能:检查语法@Deprecated:被@Deprecated标记的方法,idea/eclipse会提供功能:把使用方法的代码划掉@SuppressWarning:压制警告,idea/eclipse不会显示警告信息
-
辅助生成文档:
@author:作者@version:版本
-
代替xml配置文件:
@WebServlet:Tomcat软件提供的,用于配置Servlet,代替web.xml的
2. 定义注解
2.1 定义注解的语法
@元注解
public @interface 注解名称{
属性类型 属性名称() [default 默认值];
...
}
例如:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, MODULE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
2.2 元注解
元注解:由JDK提供的,用于限制/修饰自定义注解的注解。常见有的2个:
-
@Target:用来限制自定义注解可以用在什么地方。从ElementType里取值的,常用值有:ElementType.TYPE:可以用在类、接口上ElementType.METHOD:可以用在方法上ElementType.FIELD:可以用在字段(成员变量)上
-
@Retention:用来限制自定义注解保留到什么阶段(生命周期)。从RetentionPolicy里取值,常用的:RetentionPolicy.SOURCE:保留到源码阶段RetentionPolicy.CLASS:保留到字节码阶段RetentionPolicy.RUNTIME:保留到运行阶段
2.3 注解的属性
注解的属性,并非所有类型都可以。只支持:
- 8种基本数据类型
- String类型
- Class类型
- 注解类型
- 枚举类型:enum
- 以及以上类型的一维数组形式
2.4 自定义注解示例
@Target({ElementType.METHOD, ElementType.FIELD})//可以用在方法上、字段上
@Retention(RetentionPolicy.RUNTIME)//保留到运行阶段
public @interface MyAnno {
String value() default "default value";
String[] abc() default "abc";
}
2.5 注解的本质
我们可以打开文件夹,找到MyAnno.class所在的路径,打开cmd,执行命令:javap MyAnno.class查看字节码内容:
- 注解的本质是一个接口,它继承了
java.lang.annotation.Annotation父接口; - 注解里的属性,其实是接口里的一个抽象方法
- 我们在使用注解时添加的
@MyAnno,其实是接口的实现类对象
3. 使用注解★
3.1 注解的使用方式
@注解名(属性名=值, 属性名=值,...)- 如果某个属性有默认值,在使用注解时,可以不用再赋值;如果没有默认值,使用时就必须赋值
value属性的特殊情况:
- 如果注解里只有一个属性要赋值,并且属性名称是value,使用时可以简写成:
@注解名(值)。 - 这个值就是设置给value参数的
3.2注解使用示例
public class Demo01MyAnnoTest {
//不给属性赋值,所有属性使用默认值
@MyAnno
private String str1;
//给abc属性赋值aaaa,value属性不赋值(使用默认值)
@MyAnno(abc="aaaa")
private String str2;
//给value属性赋值,abc属性不赋值(使用默认值)。只给value赋值,可以省略"value="不写
@MyAnno("value的值")
private String str3;
//给abc和value两个属性都赋值
@MyAnno(abc = "aaaa", value = "value的值")
private String str4;
@MyAnno(value = "VALUE1", abc = "abcabc")
public void show(){
System.out.println("======show()======");
}
}
4. 解析注解
我们知道,注解本身是没有任何功能的,仅仅是相当于一个记号(标记)。把注解(记号)标记在某个类上或方法上,在使用反射调用时,可以根据注解上是否有注解,来增加不同的功能代码
4.1 解析注解相关API
Class、Constructor,Method和Field都实现了AnnotatedElement接口中注解相关的方法
常用的方法有:
| 方法 | 参数 | 返回值 |
|---|---|---|
isAnnotationPresent(Class annoClass) | 注解类型 | boolean,是否有此注解 |
getAnnotation(Class annoClass) | 注解对象 |
4.2 示例代码
public class Demo02MyAnnoParser{
@MyAnno(value = "VALUE1", abc = "abcabc")
public void show(){
System.out.println("======show()======");
}
//如果show方法上有MyAnno注解,并且value值值是"VALUE",则执行show方法;否则不执行
public static void main(String[] args) throws Exception {
Demo02MyAnnoParser demo = new Demo02MyAnnoParser();
Method method = demo.getClass().getMethod("show");
//判断方法上是否有MyAnno注解
boolean b = method.isAnnotationPresent(MyAnno.class);
System.out.println("DemoMyAnnoParseTest类上有MyAnno注解吗?" + b);
if (b) {
//获取方法配置的注解对象
MyAnno myAnno = method.getAnnotation(MyAnno.class);
//获取注解对象的属性值
String value = myAnno.value();
String[] abc = myAnno.abc();
System.out.println("value:" + value);
System.out.println("abc:" + Arrays.toString(abc));
}
}
}