Java 注解

对于注解 Annotation 是从 Java 1.5 开始加入,对于 Java 17 来说,主要是来自模块 java.base 下的包java.lang.annotation。该包提供了 Java 编程语言注解的类库支持。

在没有注解之前, Java 中大量的使用了 XML 配置文件的方式, 比如 Java 之首的 Spring 框架, 在 3.0之前,之后也保留了 xml 配置的方式, 来进行框架相关的配置。 这在项目越来越大的情况下配置文件越来越多,越繁杂,无疑对开发和使用都不是友好的,这个时候就引入了注解Annotation。

对于Java中的注解实现方式是基于源码实现, 对于使用注解和非注解的编程方式,编译的字节码都是一样的。

Java 注解_第1张图片

 使用注解格式
注解的格式,通常情况下使用 @ 符号开始,后面跟上对应的注解名称,以及注解参数和对应的值。
@注解名称([{标识符=元素的值,
标识符={元素的值,元素的值,元素的值},
标识符=Annotation
}])

使用lombok组件,通过注解自动生成一些样板代码,如getter和setter方法、构造函数、equals和hashCode方法等。

未使用lombok组件前

Java 注解_第2张图片

使用Lombok插件后

我们只需加一个注解,LomBok即可自动帮我们生成get和set方法

Java 注解_第3张图片

 使用Lombok,如果IDEA版本在2020.3以上,不需要安装Lombok插件。如果IDEA版本在2020.3以下,需要安装Lombok插件

打开设置,找到Plugins,直接搜索安装就行

Java 注解_第4张图片

 下载lombok.jar  给项目添加依赖

Downloadhttps://projectlombok.org/download 下载lombok.jar,并把下载的jar包添加依赖到项目中就可以使用了,如需了解更多,可以看这篇文章

IDEA必装插件:Lombok、GenerateAllSetter_idea生成实体类的插件_Bridge Fish的博客-CSDN博客icon-default.png?t=N6B9https://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 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注解前,会有警告

Java 注解_第5张图片

 使用后,忽略警告

Java 注解_第6张图片

自定义注解 

我们自定义注解类时,使用的注解,声明注解类时使用的注解。

元注解,本质是注解的注解。

@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 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());
    }
}

Java 注解_第7张图片

 总结
注释程序人员查看源码时看 ,注解 jvm运行字节码文件时查看信息
1. 如果注解难于理解,你就把它类同于标签,标签为了解释事物,注解为了反射读取解释代码执行。
2. 注解的基本语法,创建如同接口,但是多了个 @ 符号。 public @interface Ann{}
3. 注解的元注解 @Documented @Retention @Target
4. 注解的属性 String value(); String name() default “james” int age() default 18
5. 注解主要给编译器及工具类型 ( 框架 ) 的软件用的。
6. 注解的提取需要借助于 Java 的反射技术,反射比较慢 ( 但功能强大,是开发框架人员必须掌握,也是标志升级为动态语句的方式) ,所以注解使用时也需要谨慎计算时间成本。

你可能感兴趣的:(java,开发语言)