对于注解 Annotation 是从 Java 1.5 开始加入,对于 Java 17 来说,主要是来自模块 java.base 下的包java.lang.annotation。该包提供了 Java 编程语言注解的类库支持。
在没有注解之前, Java 中大量的使用了 XML 配置文件的方式, 比如 Java 之首的 Spring 框架, 在 3.0之前,之后也保留了 xml 配置的方式, 来进行框架相关的配置。 这在项目越来越大的情况下配置文件越来越多,越繁杂,无疑对开发和使用都不是友好的,这个时候就引入了注解Annotation。
对于Java中的注解实现方式是基于源码实现, 对于使用注解和非注解的编程方式,编译的字节码都是一样的。
使用注解格式
@注解名称([{标识符=元素的值,
标识符={元素的值,元素的值,元素的值},
标识符=Annotation
}])
使用lombok组件,通过注解自动生成一些样板代码,如getter和setter方法、构造函数、equals和hashCode方法等。
未使用lombok组件前
使用Lombok插件后
我们只需加一个注解,LomBok即可自动帮我们生成get和set方法
使用Lombok,如果IDEA版本在2020.3以上,不需要安装Lombok插件。如果IDEA版本在2020.3以下,需要安装Lombok插件
打开设置,找到Plugins,直接搜索安装就行
下载lombok.jar 给项目添加依赖
Downloadhttps://projectlombok.org/download 下载lombok.jar,并把下载的jar包添加依赖到项目中就可以使用了,如需了解更多,可以看这篇文章
IDEA必装插件:Lombok、GenerateAllSetter_idea生成实体类的插件_Bridge Fish的博客-CSDN博客https://blog.csdn.net/qq_57570052/article/details/131694239?ops_request_misc=&request_id=7da6599d226346a3845d0b55607970cb&biz_id=&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~koosearch~default-1-131694239-null-null.268^v1^control&utm_term=IDEA%E5%BF%85%E8%A3%85%E6%8F%92%E4%BB%B6%EF%BC%9ALombok%E3%80%81GenerateAllSetter&spm=1018.2226.3001.4450
内置注解
代码注解
标注在代码里面的注解,称为代码注解
注解 | 描述 |
---|---|
override | 标记在子类中重写了父类的方法,如果不是则会报错 |
deprecated | 标记此方法已经过时了 |
suppressWarnings | 忽略注解声明的警告 |
元注解
元注解可以理解为注解的注解
注解 | 描述 |
---|---|
retention | 标记注解怎么保存 |
documented | 使用此注解可以让注解保存到javadoc文档中 |
target | 标记注解的作用域 |
Inherirted | 标记注解有继承性 |
新增的注解
注解 | 描述 |
---|---|
SafavarArgs | 忽略方法或者构造方法的参数为泛型所产生的警告 |
FuntionalInterface | 标注一个函数性接口 |
repeatable | 标识某注解可以在同一个声明上使用多次 |
JAVA注解三大类
每一个annotation都有多个elementType和唯一的一个retentionPolicy
1.Annotation接口
package java.lang.annotation;
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
2.ElementType枚举
public enum ElementType {
TYPE, //在接口、类、枚举上声明注解
METHOD,//在方法上声明注解
FIELD,//在字段上声明注解
PARAMETER,//在参数上声明注解
LOCAL_VARIABLE,//在局部变量上声明注解
PACKET,在包上声明注解
CONSTRUCTOR,//在构造方法上声明注解
ANNOTATIONTYPE,//在注解类型上声明注解
}
3.RtentionPolicy枚举
public enum RtentionPolicy {
SOURCE, //注解信息存在代码的编译过程,编译结束,注解结束
CLASS, //注解信息保存在字节码文件中
RUNTIME //注解信息保存在字节码文件中,并可以被JVM虚拟机读取
}
4.举例SuppressWarnings详解
@Doucumented
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
- @Doucumented代表的是SuppressWarnings注解可以保存javadoc文档里面的
- @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) 表示的是该注解可以作用域。
- @Retention(RetentionPolicy.SOURCE) 表示注解仅仅在存在编译期间,编译结束则消失
- String[] value();表示SuppressWarnings 有多个值;
SuppressWarnings的常用关键字
关键字 | 描述 |
---|---|
deprecation | 忽略使用不被赞成、过时所产生的警告 |
unchecked | 忽略集合中没有声明类型的所产生的警告 |
fallthrouth | switch程序块,忽略下一种情况没有break的情况 |
path | 忽略类地址、源路径不存在的警告 |
serial | 序列化的时候,忽略类中缺少serialVersionUUid警告 |
finally | 忽略finally语句块不能正常执行的的警告 |
path | 忽略类地址、源路径不存在的警告 |
serial | 序列化的时候,忽略类中缺少serialVersionUUid警告 |
finally | 忽略finally语句块不能正常执行的的警告 |
public class A {
void show() {
}
}
未使用SuppressWarnings注解前,会有警告
使用后,忽略警告
自定义注解
我们自定义注解类时,使用的注解,声明注解类时使用的注解。
元注解,本质是注解的注解。
@Documented 该注解是一个标注注解, 主要是为了进行 javadoc 生成代码的时候, 显示注解内容。
@Retention注解接口 可以理解该接口的生命周期, 也就是在运行时保留该注解多少时间。
也就是说对于 Retention 注解的接口参数就三个,分别是: RetentionPolicy.CLASS,
RetentionPolicy.RUNTIME 以及 RetentionPolicy.SOURCE。如果注解接口不包含该注解,则默认的策略是:RetentionPolicy.CLASS
- RetentionPolicy.CLASS: 编译器将把注释记录在class文件中。当运行Java程序时,JVM不在保留注释,这是默认值。
- RetentionPolicy.RUNTIME: 编译器将把注释记录在class文件中。当运行Java程序时,JVM也会保留注释,程序可以通过反射获取该注释。
- RetentionPolicy.SOURCE: 注解仅存在于源码中,在class字节码文件中不包含。
声明注解类方式:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface My {
}
@Target 对于 @Target 注解接口,是注解接口的上下文,注解对象所在的位置
@Target也是用于修饰一个Annotation定义,它用于指定被修饰Annotation能用于修饰那些程序元素。
@Target Annotation也包含一个名为value的成员变量,该成员变量只能是如下几个:
- ElementType.ANNOTATION_TYPE: 指定该策略的Annotation只能修饰Annotation。
- ElementType.CONSTRUCTOR: 指定该策略的Annotation能修饰构造器。
- ElementType.FIELD: 指定该策略的Annotation只能修饰成员变量。
- ElementType.LOCAL_VARIABLE: 指定该策略的Annotation只能修饰局部变量。
- ElementType.METHOD: 指定该策略的Annotation只能修饰方法。
- ElementType.PACKAGE: 指定该策略的Annotation只能修饰包定义。
- ElementType.PARAMETER: 指定该策略的Annotation可以修饰参数。
- ElementType.TYPE: 指定该策略的Annotation可以修饰类、接口(包括注释类型)或枚举定义。
声明注解
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Target({TYPE, METHOD, PARAMETER, FIELD, LOCAL_VARIABLE}) //type 类上 method 方法上 parameter 参数变量上 field 属性上
@Retention(RUNTIME)
public @interface Ann {
String name();
int age();
String sex() default "男";
}
使用注解
@Ann(name = "李丽", age = 18, sex = "女")
public class User {
@Ann(name = "李丽", age = 18)
String name;
@Ann(name = "张三丰", age = 22)
public void show(@Ann(name = "jack", age = 55) Ann ann) {
@Ann(name = "lisi", age = 11)
String lisi = "lisi11";
}
}
使用自定义注解需要反射技术
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
public class UserDemo {
public static void main(String[] args) throws Exception {
Class<User> c = User.class;
// 反射类读取类上的注解信息
Ann ann = c.getAnnotation(Ann.class);
System.out.println(ann.name());
System.out.println(ann.age());
System.out.println(ann.sex());
// 反射类字段上的注解信息
Field f = c.getDeclaredField("name");
Ann fann = f.getAnnotation(Ann.class);
System.out.println(fann.name());
System.out.println(fann.age());
System.out.println(fann.sex());
// 反射类方法上的注解信息
Method show = c.getMethod("show", Ann.class);
System.out.println(show);
Ann sann = show.getAnnotation(Ann.class);
System.out.println(sann.name());
System.out.println(sann.age());
System.out.println(sann.sex());
// 反射方法参数上的注解信息
Parameter par = show.getParameters()[0];
Ann annotation = par.getAnnotation(Ann.class);
System.out.println(annotation.name());
System.out.println(annotation.age());
System.out.println(annotation.sex());
}
}