0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Java注解及其底层原理解析 1

jf_78858299 来源:小牛呼噜噜 作者:小牛呼噜噜 2023-02-09 14:18 次阅读

什么是注解?

当我们开发SpringBoot项目,我们只需对启动类加上@SpringBootApplication,就能自动装配,不需要编写冗余的xml配置。当我们为项目添加lombok依赖,使用@Data来修饰实体类,我们就不需要编写getter和setter方法,构造函数等等。@SpringBootApplication,@Data等像这种以**"@"**开头的代码 就是 注解, 只需简简单单几个注解,就能帮助我们省略大量冗余的代码,这是一个非常不可思议的事情!

但我们往往知道在哪些地方加上合适的注解,不然IDE会报错,却不知道其中的原理,那究竟什么是注解呢?

注解(Annotation ), 是 Java5 开始引入的新特性,是放在Java源码的类、方法、字段、参数前的一种特殊“注释”, 是一种标记、标签 注释往往会被编译器直接忽略,能够被编译器打包进入class文件,并执行相应的处理。

按照惯例我们去看下注解的源码:

先新建一个注解文件:MyAnnotation.java

public @interface MyAnnotation {
}

发现MyAnnotation 是被@interface修饰的,感觉和接口interface很像。

我们再通过idea来看下其的类继承:

图片

MyAnnotation 是继承Annotation接口的。

我们再反编译一下:

$ javac MyAnnotation.java
$ javap -c MyAnnotation

Compiled from "MyAnnotation.java"
public interface com.zj.ideaprojects.test3.MyAnnotation extends java.lang.annotation.Annotation {
}

发现生成的字节码中 @interface变成了interface,MyAnnotation而且自动继承了Annotation

我们由此可以明白:注解本质是一个继承了Annotation 的特殊接口, 所以注解也叫声明式接口

注解的分类

一般常用的注解可以分为三大类:

Java自带的标准注解

例如:

  • @Override:让编译器检查该方法是否正确地实现了覆写;
  • @SuppressWarnings:告诉编译器忽略此处代码产生的警告。
  • @Deprecated:标记过时的元素,这个我们经常在日常开发中经常碰到。
  • @FunctionalInterface:表明函数式接口注解

元注解

元注解是能够用于定义注解的注解, 或者说元注解是一种基本注解,包括@Retention、@Target、@Inherited、@Documented、@Repeatable 等

元注解也是Java自带的标准注解,只不过用于修饰注解,比较特殊。

@Retention

注解的保留策略, @Retention 定义了Annotation的生命周期 。当 @Retention 应用到一个注解上的时候,它解释说明了这个注解的的存活时间。

它的参数:

RetentionPolicy.SOURCE 注解只在源码阶段保留,在编译器进行编译时它将被丢掉
RetentionPolicy.CLASS 注解只被保留到编译进行的时候,它并不会被加载到 JVM 中
RetentionPolicy.RUNTIME 注解可以保留到程序运行中的时候,它会被加载进 JVM中,在程序运行中也可以获取到它们

如果@Retention不存在,则该Annotation默认为RetentionPolicy.CLASS

示例:

@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation { 
}

我们自定义的TestAnnotation 可以在程序运行中被获取到

@Documented

它的作用是 用于 制作文档 ,将注解中的元素包含到 doc 中

一般不怎么用到,了解即可

@Target

@Target 指定了注解可以修饰哪些地方 , 比如方法、成员变量、还是包等等

当一个注解被 @Target 注解时,这个注解就被限定了运用的场景。

常用的参数如下:

ElementType.ANNOTATION_TYPE 给一个注解进行注解
ElementType.CONSTRUCTOR 给构造方法进行注解
ElementType.FIELD 给属性进行注解
ElementType.LOCAL_VARIABLE 给局部变量进行注解
ElementType.METHOD 给方法进行注解
ElementType.PACKAGE 给包进行注解
ElementType.PARAMETER 给一个方法内的参数进行注解
ElementType.TYPE 给一个类型进行注解,比如类、接口、枚举

@Inherited

@Inherited 修饰一个类时,表明它的注解可以被其子类 继承 ,缺省情况默认是不继承的。

换句话说:如果一个子类想获取到父类上的注解信息,那么必须在父类上使用的注解上面 加上@Inherit关键字

注意:

  • @Inherited仅针对@Target(ElementType.TYPE)类型的annotation有效
  • @Inherited 不是表明 注解可以继承,而是子类可以继承父类的注解

我们来看一个示例:

定义一个注解:

@Inherited
@Target(ElementType.TYPE)
public @interface MyReport {
    String name() default "";
    int value() default 0;
}

使用这个注解:

@MyReport(value=1)
public class Teacher {
}

则它的子类默认继承了该注解:

public class Student extends Teacher{
    
}

idea 查看类的继承关系:

图片

【图重截】

@Repeatable

使用@Repeatable这个元注解来申明注解,表示这个声明的注解是可重复的

@Repeatable 是 Java 1.8 才加进来的,所以算是一个新的特性。

比如:一个人他既会下棋又会做饭,他还会唱歌。

@Repeatable(MyReport.class)
@Target(ElementType.TYPE)
public @interface MyReport {
    String name() default "";
    int value() default 0;
}

@MyReport(value=0)
@MyReport(value=1)
@MyReport(value=2)
public class Man{
}

自定义注解

我们可以根据自己的需求定义注解,一般分为以下几步:

  1. 新建注解文件, @interface定义注解
public @interface MyReport { }
  1. 添加参数、默认值
public @interface MyReport {
    String name() default "";
    int value() default 0;
}
  1. 用元注解配置注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyReport {
    String name() default "";
    int value() default 0;
}

我们一般设置 @Target和@Retention就够了,其中@Retention一般设置为RUNTIME,因为我们自定义的注解通常需要在程序运行中读取。

自定义注解的读取

读到这里,相信大家已经明白了 如何定义使用注解,我们接下来 就需要如何将注解利用起来。

我们知道读取注解, 需要用到java的反射

推荐阅读笔者之前写过关于反射的文章:https://mp.weixin.qq.com/s/_n8HTIjkw7Emcunpb4-Iwg

我们先来写一个简单的示例-- 反射获取注解

通过前文的了解,先来改造一下MyAnnotation.java

@Retention(RetentionPolicy.RUNTIME)//确保程序运行中,能够读取到该注解!!!
public @interface MyAnnotation {
    String msg() default "no msg";
}

我们再用@MyAnnotation来修饰Person类的类名、属性、和方法

@MyAnnotation(msg = "this person class")//注解 修饰类
public class Person {

    private String name;//姓名
    private String sex;//性别

    @MyAnnotation(msg = "this person field public")//注解 修饰 public属性
    public int height;//身高

    @MyAnnotation(msg = "this person field private")//注解 修饰 private属性
    private int weight;//体重


    public void sleep(){
        System.out.println(this.name+"--"+ "睡觉");
    }
    public void eat(){
        System.out.println("吃饭");
    }

    @MyAnnotation(msg = "this person method")//注解 修饰方法
    public void dance(){
        System.out.println("跳舞");
    }
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2959

    浏览量

    104553
  • XML
    XML
    +关注

    关注

    0

    文章

    188

    浏览量

    33043
  • spring
    +关注

    关注

    0

    文章

    338

    浏览量

    14311
收藏 人收藏

    评论

    相关推荐

    如何通过注解来优化我们的Java代码

    Java注解可以说是我们编码过程中最常用的。本篇文章将给大家介绍Java注解的概念、作用以及如何使用注解来提升代码的可读性和灵活性,并介绍如
    的头像 发表于 09-30 11:39 593次阅读

    java经典面试题深度解析

    免费视频教程:java经典面试题深度解析对于很多初学者来说,学好java在后期面试的阶段都没什么经验,为了让大家更好的了解面试相关知识,今天在这里给大家分享了一个java经典面试题深度
    发表于 06-20 15:16

    详细介绍了Java泛型、注解、并发编程

    介绍了Java泛型、注解、并发编程、数据传输与序列化、高效IO、容器集合、反射与类加载以及JVM重点知识线程、内存模型、JVM运行时内存、垃圾回收与算法、Java中四种引用类型、GC 分代收集算法
    发表于 08-20 06:09

    HarmonyOS注解的使用方法分享

    定义我们的注解自定义注解1、声明注解功能:检测类中是否有规范的get方法新建java libray的module,命名为annotation
    发表于 03-28 14:04

    分析java注解基本概念

    什么是注解(Annotation): Annotation(注解)就是Java提供了一种元程序中的元素关联任何信息和着任何元数据(metadata)的途径和方法。Annotion(注解
    发表于 09-27 14:53 0次下载

    网易Java程序员两轮面试问题经验

    part 1 网易JAVA程序员一面 1.volatile有什么用? 2.Minor GC和Full GC的触发时机 3.反射用到了哪些接口,哪些类? 4.反射机制中可以获取private成员
    发表于 11-29 08:38 896次阅读

    Java底层实现,CPU还有10个术语!

    Java底层实现——CPU的10个术语
    的头像 发表于 03-28 14:14 6219次阅读

    注解定义Bean及开发

    注解本质是一个继承了Annotation 的特殊接口,其具体实现类是Java 运行时生成的动态代理类。
    发表于 08-02 10:26 432次阅读

    Java注解及其底层理解析2

    什么是注解? 当我们开发SpringBoot项目,我们只需对启动类加上`@SpringBootApplication`,就能自动装配,不需要编写冗余的xml配置。当我们为项目添加lombok
    的头像 发表于 02-09 14:18 486次阅读
    <b class='flag-5'>Java</b><b class='flag-5'>注解</b><b class='flag-5'>及其</b><b class='flag-5'>底层</b>原<b class='flag-5'>理解析</b>2

    容器配置及Spring Boot注解

    Autowired注解用于标记Spring将要解析和注入的依赖项。此注解可以作用在构造函数、字段和setter方法上。
    的头像 发表于 04-07 11:45 558次阅读
    容器配置及Spring Boot<b class='flag-5'>注解</b>

    SpringBoot的核心注解1

    今天跟大家来探讨下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot为什么不需要XML,达到零配置
    的头像 发表于 04-07 14:34 673次阅读
    SpringBoot的核心<b class='flag-5'>注解</b><b class='flag-5'>1</b>

    JAVA注解是怎么做到的(上)

    。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。那么你知道JDK什么是元注解吗?注解有哪些分类吗?以及注解Java中最本质究竟是什么东西,
    的头像 发表于 05-11 10:57 624次阅读

    JAVA注解是怎么做到的(下)

    。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。那么你知道JDK什么是元注解吗?注解有哪些分类吗?以及注解Java中最本质究竟是什么东西,
    的头像 发表于 05-11 10:57 549次阅读
    <b class='flag-5'>JAVA</b>中<b class='flag-5'>注解</b>是怎么做到的(下)

    3分钟纯Java注解搭个管理系统

    Erupt一个通用后台管理框架,据说有 超低代码量 、 零前端代码 、零 CURD操作 、无需建表 ,纯Java注解开发 等特色,号称三分钟就可以搭建一个完整的后台管理系统。
    的头像 发表于 07-28 11:27 1050次阅读
    3分钟纯<b class='flag-5'>Java</b><b class='flag-5'>注解</b>搭个管理系统

    springmvc常用5种注解

    SpringMVC是一种基于Java的Web框架,使用注解可以更加方便灵活地开发和管理控制器,实现请求的映射和处理。在SpringMVC中,有许多常用的注解,本文将详细介绍其中的五种注解
    的头像 发表于 11-22 16:51 816次阅读