0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

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

jf_78858299 ? 來源:小牛呼嚕嚕 ? 作者:小牛呼嚕嚕 ? 2023-02-09 14:18 ? 次閱讀

什么是注解?

當(dāng)我們開發(fā)SpringBoot項(xiàng)目,我們只需對(duì)啟動(dòng)類加上@SpringBootApplication,就能自動(dòng)裝配,不需要編寫冗余的xml配置。當(dāng)我們?yōu)轫?xiàng)目添加lombok依賴,使用@Data來修飾實(shí)體類,我們就不需要編寫getter和setter方法,構(gòu)造函數(shù)等等。@SpringBootApplication,@Data等像這種以**"@"**開頭的代碼 就是 注解, 只需簡簡單單幾個(gè)注解,就能幫助我們省略大量冗余的代碼,這是一個(gè)非常不可思議的事情!

但我們往往知道在哪些地方加上合適的注解,不然IDE會(huì)報(bào)錯(cuò),卻不知道其中的原理,那究竟什么是注解呢?

注解(Annotation ), 是 Java5 開始引入的新特性,是放在Java源碼的類、方法、字段、參數(shù)前的一種特殊“注釋”, 是一種標(biāo)記、標(biāo)簽。 注釋往往會(huì)被編譯器直接忽略,能夠被編譯器打包進(jìn)入class文件,并執(zhí)行相應(yīng)的處理。

按照慣例我們?nèi)タ聪伦⒔獾脑创a:

先新建一個(gè)注解文件:MyAnnotation.java

public @interface MyAnnotation {
}

發(fā)現(xiàn)MyAnnotation 是被@interface修飾的,感覺和接口interface很像。

我們?cè)偻ㄟ^idea來看下其的類繼承:

圖片

MyAnnotation 是繼承Annotation接口的。

我們?cè)俜淳幾g一下:

$ javac MyAnnotation.java
$ javap -c MyAnnotation

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

發(fā)現(xiàn)生成的字節(jié)碼中 @interface變成了interface,MyAnnotation而且自動(dòng)繼承了Annotation

我們由此可以明白:注解本質(zhì)是一個(gè)繼承了Annotation 的特殊接口, 所以注解也叫聲明式接口

注解的分類

一般常用的注解可以分為三大類:

Java自帶的標(biāo)準(zhǔn)注解

例如:

  • @Override:讓編譯器檢查該方法是否正確地實(shí)現(xiàn)了覆寫;
  • @SuppressWarnings:告訴編譯器忽略此處代碼產(chǎn)生的警告。
  • @Deprecated:標(biāo)記過時(shí)的元素,這個(gè)我們經(jīng)常在日常開發(fā)中經(jīng)常碰到。
  • @FunctionalInterface:表明函數(shù)式接口注解

元注解

元注解是能夠用于定義注解的注解, 或者說元注解是一種基本注解,包括@Retention、@Target、@Inherited、@Documented、@Repeatable 等

元注解也是Java自帶的標(biāo)準(zhǔn)注解,只不過用于修飾注解,比較特殊。

@Retention

注解的保留策略, @Retention 定義了Annotation的生命周期 。當(dāng) @Retention 應(yīng)用到一個(gè)注解上的時(shí)候,它解釋說明了這個(gè)注解的的存活時(shí)間。

它的參數(shù):

RetentionPolicy.SOURCE 注解只在源碼階段保留,在編譯器進(jìn)行編譯時(shí)它將被丟掉
RetentionPolicy.CLASS 注解只被保留到編譯進(jìn)行的時(shí)候,它并不會(huì)被加載到 JVM 中
RetentionPolicy.RUNTIME 注解可以保留到程序運(yùn)行中的時(shí)候,它會(huì)被加載進(jìn) JVM中,在程序運(yùn)行中也可以獲取到它們

如果@Retention不存在,則該Annotation默認(rèn)為RetentionPolicy.CLASS

示例:

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

我們自定義的TestAnnotation 可以在程序運(yùn)行中被獲取到

@Documented

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

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

@Target

@Target 指定了注解可以修飾哪些地方 , 比如方法、成員變量、還是包等等

當(dāng)一個(gè)注解被 @Target 注解時(shí),這個(gè)注解就被限定了運(yùn)用的場(chǎng)景。

常用的參數(shù)如下:

ElementType.ANNOTATION_TYPE 給一個(gè)注解進(jìn)行注解
ElementType.CONSTRUCTOR 給構(gòu)造方法進(jìn)行注解
ElementType.FIELD 給屬性進(jìn)行注解
ElementType.LOCAL_VARIABLE 給局部變量進(jìn)行注解
ElementType.METHOD 給方法進(jìn)行注解
ElementType.PACKAGE 給包進(jìn)行注解
ElementType.PARAMETER 給一個(gè)方法內(nèi)的參數(shù)進(jìn)行注解
ElementType.TYPE 給一個(gè)類型進(jìn)行注解,比如類、接口、枚舉

@Inherited

@Inherited 修飾一個(gè)類時(shí),表明它的注解可以被其子類 繼承 ,缺省情況默認(rèn)是不繼承的。

換句話說:如果一個(gè)子類想獲取到父類上的注解信息,那么必須在父類上使用的注解上面 加上@Inherit關(guān)鍵字

注意:

  • @Inherited僅針對(duì)@Target(ElementType.TYPE)類型的annotation有效
  • @Inherited 不是表明 注解可以繼承,而是子類可以繼承父類的注解

我們來看一個(gè)示例:

定義一個(gè)注解:

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

使用這個(gè)注解:

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

則它的子類默認(rèn)繼承了該注解:

public class Student extends Teacher{
    
}

idea 查看類的繼承關(guān)系:

圖片

【圖重截】

@Repeatable

使用@Repeatable這個(gè)元注解來申明注解,表示這個(gè)聲明的注解是可重復(fù)的

@Repeatable 是 Java 1.8 才加進(jìn)來的,所以算是一個(gè)新的特性。

比如:一個(gè)人他既會(huì)下棋又會(huì)做飯,他還會(huì)唱歌。

@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{
}

自定義注解

我們可以根據(jù)自己的需求定義注解,一般分為以下幾步:

  1. 新建注解文件, @interface定義注解
public @interface MyReport { }
  1. 添加參數(shù)、默認(rèn)值
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;
}

我們一般設(shè)置 @Target和@Retention就夠了,其中@Retention一般設(shè)置為RUNTIME,因?yàn)槲覀冏远x的注解通常需要在程序運(yùn)行中讀取。

自定義注解的讀取

讀到這里,相信大家已經(jīng)明白了 如何定義使用注解,我們接下來 就需要如何將注解利用起來。

我們知道讀取注解, 需要用到j(luò)ava的反射

推薦閱讀筆者之前寫過關(guān)于反射的文章:https://mp.weixin.qq.com/s/_n8HTIjkw7Emcunpb4-Iwg

我們先來寫一個(gè)簡單的示例-- 反射獲取注解

通過前文的了解,先來改造一下MyAnnotation.java

@Retention(RetentionPolicy.RUNTIME)//確保程序運(yùn)行中,能夠讀取到該注解?。?!
public @interface MyAnnotation {
    String msg() default "no msg";
}

我們?cè)儆?code>@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("跳舞");
    }
}
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2973

    瀏覽量

    104939
  • XML
    XML
    +關(guān)注

    關(guān)注

    0

    文章

    188

    瀏覽量

    33110
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14364
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何通過注解來優(yōu)化我們的Java代碼

    Java注解可以說是我們編碼過程中最常用的。本篇文章將給大家介紹Java注解的概念、作用以及如何使用注解來提升代碼的可讀性和靈活性,并介紹如
    的頭像 發(fā)表于 09-30 11:39 ?668次閱讀

    java經(jīng)典面試題深度解析

    免費(fèi)視頻教程:java經(jīng)典面試題深度解析對(duì)于很多初學(xué)者來說,學(xué)好java在后期面試的階段都沒什么經(jīng)驗(yàn),為了讓大家更好的了解面試相關(guān)知識(shí),今天在這里給大家分享了一個(gè)java經(jīng)典面試題深度
    發(fā)表于 06-20 15:16

    詳細(xì)介紹了Java泛型、注解、并發(fā)編程

    介紹了Java泛型、注解、并發(fā)編程、數(shù)據(jù)傳輸與序列化、高效IO、容器集合、反射與類加載以及JVM重點(diǎn)知識(shí)線程、內(nèi)存模型、JVM運(yùn)行時(shí)內(nèi)存、垃圾回收與算法、Java中四種引用類型、GC 分代收集算法
    發(fā)表于 08-20 06:09

    HarmonyOS注解的使用方法分享

    定義我們的注解自定義注解1、聲明注解功能:檢測(cè)類中是否有規(guī)范的get方法新建java libray的module,命名為annotation
    發(fā)表于 03-28 14:04

    分析java注解基本概念

    什么是注解(Annotation): Annotation(注解)就是Java提供了一種元程序中的元素關(guān)聯(lián)任何信息和著任何元數(shù)據(jù)(metadata)的途徑和方法。Annotion(注解
    發(fā)表于 09-27 14:53 ?0次下載

    Java底層實(shí)現(xiàn),CPU還有10個(gè)術(shù)語!

    Java底層實(shí)現(xiàn)——CPU的10個(gè)術(shù)語
    的頭像 發(fā)表于 03-28 14:14 ?6276次閱讀

    注解定義Bean及開發(fā)

    注解本質(zhì)是一個(gè)繼承了Annotation 的特殊接口,其具體實(shí)現(xiàn)類是Java 運(yùn)行時(shí)生成的動(dòng)態(tài)代理類。
    發(fā)表于 08-02 10:26 ?454次閱讀

    插入式注解處理器使用記錄

    插入式注解處理器在《深入理解Java虛擬機(jī)》一書中有一些介紹(前端編譯篇有提到),但一直沒有機(jī)會(huì)使用,直到碰到這個(gè)需求,覺得再合適不過了,就簡單用了一下,這里做個(gè)記錄。
    的頭像 發(fā)表于 01-31 16:47 ?489次閱讀

    Java注解及其底層理解析2

    什么是注解? 當(dāng)我們開發(fā)SpringBoot項(xiàng)目,我們只需對(duì)啟動(dòng)類加上`@SpringBootApplication`,就能自動(dòng)裝配,不需要編寫冗余的xml配置。當(dāng)我們?yōu)轫?xiàng)目添加lombok
    的頭像 發(fā)表于 02-09 14:18 ?531次閱讀
    <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注解用于標(biāo)記Spring將要解析和注入的依賴項(xiàng)。此注解可以作用在構(gòu)造函數(shù)、字段和setter方法上。
    的頭像 發(fā)表于 04-07 11:45 ?605次閱讀
    容器配置及Spring Boot<b class='flag-5'>注解</b>

    SpringBoot的核心注解1

    今天跟大家來探討下SpringBoot的核心注解@SpringBootApplication以及run方法,理解下springBoot為什么不需要XML,達(dá)到零配置
    的頭像 發(fā)表于 04-07 14:34 ?722次閱讀
    SpringBoot的核心<b class='flag-5'>注解</b><b class='flag-5'>1</b>

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

    。它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等的前面,用來對(duì)這些元素進(jìn)行說明,注釋。那么你知道JDK什么是元注解嗎?注解有哪些分類嗎?以及注解Java中最本質(zhì)究竟是什么東西,
    的頭像 發(fā)表于 05-11 10:57 ?667次閱讀

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

    。它可以聲明在包、類、字段、方法、局部變量、方法參數(shù)等的前面,用來對(duì)這些元素進(jìn)行說明,注釋。那么你知道JDK什么是元注解嗎?注解有哪些分類嗎?以及注解Java中最本質(zhì)究竟是什么東西,
    的頭像 發(fā)表于 05-11 10:57 ?597次閱讀
    <b class='flag-5'>JAVA</b>中<b class='flag-5'>注解</b>是怎么做到的(下)

    3分鐘純Java注解搭個(gè)管理系統(tǒng)

    Erupt一個(gè)通用后臺(tái)管理框架,據(jù)說有 超低代碼量 、 零前端代碼 、零 CURD操作 、無需建表 ,純Java注解開發(fā) 等特色,號(hào)稱三分鐘就可以搭建一個(gè)完整的后臺(tái)管理系統(tǒng)。
    的頭像 發(fā)表于 07-28 11:27 ?1141次閱讀
    3分鐘純<b class='flag-5'>Java</b><b class='flag-5'>注解</b>搭個(gè)管理系統(tǒng)

    springmvc常用5種注解

    SpringMVC是一種基于Java的Web框架,使用注解可以更加方便靈活地開發(fā)和管理控制器,實(shí)現(xiàn)請(qǐng)求的映射和處理。在SpringMVC中,有許多常用的注解,本文將詳細(xì)介紹其中的五種注解
    的頭像 發(fā)表于 11-22 16:51 ?940次閱讀