吴忠躺衫网络科技有限公司

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

    文章

    2975

    瀏覽量

    105156
  • XML
    XML
    +關注

    關注

    0

    文章

    188

    瀏覽量

    33142
  • spring
    +關注

    關注

    0

    文章

    340

    瀏覽量

    14391
收藏 人收藏

    評論

    相關推薦

    如何通過注解來優化我們的Java代碼

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

    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底層實現,CPU還有10個術語!

    Java底層實現——CPU的10個術語
    的頭像 發表于 03-28 14:14 ?6297次閱讀

    注解定義Bean及開發

    注解本質是一個繼承了Annotation 的特殊接口,其具體實現類是Java 運行時生成的動態代理類。
    發表于 08-02 10:26 ?461次閱讀

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

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

    Java注解及其底層理解析2

    什么是注解? 當我們開發SpringBoot項目,我們只需對啟動類加上`@SpringBootApplication`,就能自動裝配,不需要編寫冗余的xml配置。當我們為項目添加lombok
    的頭像 發表于 02-09 14:18 ?542次閱讀
    <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 ?616次閱讀
    容器配置及Spring Boot<b class='flag-5'>注解</b>

    SpringBoot的核心注解1

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

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

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

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

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

    3分鐘純Java注解搭個管理系統

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

    springmvc常用5種注解

    SpringMVC是一種基于Java的Web框架,使用注解可以更加方便靈活地開發和管理控制器,實現請求的映射和處理。在SpringMVC中,有許多常用的注解,本文將詳細介紹其中的五種注解
    的頭像 發表于 11-22 16:51 ?967次閱讀
    百家乐真钱电玩| 威尼斯人娱乐网反| 体育博彩| 博彩百家乐官网后一预测软件| 广州百家乐桌子| 江源县| 做生意什么花风水好| 大发888博彩官方下载| 网上百家乐官网做假| 哪家百家乐优惠最好且信誉不错| 百家乐官网为什么庄5| 网上百家乐辅助软件| 战神国际娱乐平| 真人百家乐是骗局| 皇冠在线赌场| 百家乐起步多少| 娱乐城注册送68| 财神百家乐官网的玩法技巧和规则 | 大发888 大发888官网 | 蓝盾百家乐赌场娱乐网规则| 抚顺县| 百家乐龙虎台布多少钱| 百家乐官网赚钱项目| 叶氏百家乐平注技巧| 现场百家乐官网百家乐官网| 百家乐永利娱乐场| 百家乐官网15人桌子| 新东泰百家乐的玩法技巧和规则 | 金百亿百家乐官网娱乐城| 游戏百家乐押金| 百家乐官网视频游戏挖坑| 赌百家乐的计划跟策略| 盛京棋牌网| 百家乐是否有路子| 大发888娱乐城在线存款| 巴比伦百家乐官网娱乐城| 星期八娱乐城| 在线百家乐游戏软件| 百家乐官网博彩策略| 大发888游戏平台403| 百家乐赢的方法|