Java 注解

对于注解 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  给项目添加依赖

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

IDEA必装插件:Lombok、GenerateAllSetter_idea生成实体类的插件_Bridge Fish的博客-CSDN博客icon-default.png?t=N7T8https://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%5Ev1%5Econtrol&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忽略集合中没有声明类型的所产生的警告
fallthrouthswitch程序块,忽略下一种情况没有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());
    }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bridge Fish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值