最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 注解的底層原理解析(java基礎(chǔ)面試必問)

 更新時間:2026年04月08日 09:01:28   作者:Lyyaoo.  
本文介紹了Java注解的基本概念及其生命周期、使用位置等元注解的定義和使用方法,詳細解釋了注解的在編譯、類加載和運行時的處理過程,并通過實例說明了注解在反射API中的實現(xiàn)原理,感興趣的朋友跟隨小編一起看看吧

前言

注解是 Java 5 引入的一種元數(shù)據(jù)機制,可以在代碼中添加信息,這些信息可以被編譯器、開發(fā)工具或運行時環(huán)境使用。

注解的本質(zhì)是一個繼承了Annotation的接口

 Java 注解(Annotation)是一種元數(shù)據(jù),它本身不直接影響代碼邏輯,但可以被編譯器、工具或框架在編譯時或運行時讀取并處理。

 注解實際上是一個接口,它隱式地繼承自 java.lang.annotation.Annotation 接口。注解中定義的方法對應(yīng)注解的“屬性”。這些方法沒有參數(shù),返回值類型受限(基本類型、String、Class、枚舉、注解以及它們的數(shù)組)。

 對于一個簡單的自定義注解,使用 @interface 關(guān)鍵字進行實現(xiàn)

public @interface MyAnnotation {
    String value() default "";
}

 用 javap -c MyAnnotation 反編譯后,會看到,

public interface MyAnnotation extends java.lang.annotation.Annotation {
  public abstract java.lang.String value();
}

元注解

 Java 提供了幾個元注解(即注解的注解),用來定義注解的生命周期、使用位置等。

元注解作用
@Target指定注解可以用在哪些地方(類、方法、字段、參數(shù)等)。
@Retention指定注解保留到哪個階段(源碼、字節(jié)碼、運行時)。
@Documented是否包含在 Javadoc 中。
@Inherited是否允許子類繼承父類的注解。
@Repeatable(Java 8)允許同一位置重復(fù)使用同一個注解。

@Target注解

 @Target 接收一個 ElementType 數(shù)組,表示該注解可以出現(xiàn)在哪些地方。常用的 ElementType 枚舉值包括:

ElementType說明
TYPE類、接口、枚舉、注解類型
FIELD成員變量(包括枚舉常量)
METHOD方法
PARAMETER方法參數(shù)
CONSTRUCTOR構(gòu)造方法
LOCAL_VARIABLE局部變量
ANNOTATION_TYPE注解類型(用于元注解)
PACKAGE
TYPE_PARAMETER(Java 8)類型參數(shù)(如 class MyClass 中的 T)
TYPE_USE(Java 8)類型使用處(如 new @NonNull String())

@Retention注解

  • SOURCE:注解只保留在源代碼中,編譯時被丟棄(如 @Override、@SuppressWarnings)。這類注解僅用于編譯期檢查,不會進入 .class 文件。
  • CLASS(默認):注解保留在 .class 文件中,但加載到 JVM 時會被忽略(即運行時無法通過反射獲?。?。這種級別通常用于字節(jié)碼操作工具(如 Lombok)。
  • RUNTIME:注解保留在 .class 文件中,并且在運行時可以被 JVM 讀?。ㄍㄟ^反射)。這是框架最常用的級別(如 @Autowired、@RequestMapping)。

注解在字節(jié)碼中的存儲

編譯階段

 當編譯器處理帶有注解的代碼時,會根據(jù) @Retention 決定是否將注解信息寫入 .class 文件。對于 RUNTIME 或 CLASS 級別的注解,編譯器會在字節(jié)碼中添加專門的屬性表(Attribute)。

 以 @MyAnnotation 標注一個類為例:

@MyAnnotation("hello")
public class Test {}

 用 javap -v Test 查看字節(jié)碼,會看到類似:

RuntimeVisibleAnnotations:
  0: #10(#11=s#12)
    #10 = Utf8 "LMyAnnotation;"
    #11 = Utf8 "value"
    #12 = Utf8 "hello"

 RuntimeVisibleAnnotations 是字節(jié)碼中的一種屬性,表示在運行時可見的注解列表。每個注解被編碼為:注解類型 + 屬性名 + 屬性值。例子中的類型為 LMyAnnotation;,屬性名是value,屬性值是hello。

類加載階段

 JVM 在加載類時,會讀取 .class 文件中的這些屬性,將注解信息解析并存儲到類的元數(shù)據(jù)中(方法區(qū)的 Annotation 數(shù)據(jù)結(jié)構(gòu))。但對于 @Retention(CLASS) 的注解,在類加載后這些信息會被丟棄;而對于 RUNTIME 的注解,會保留在運行時。

運行時注解(反射API)

JVM自動生成動態(tài)代理對象來實現(xiàn)注解接口,可通過代理對象的 invoke 方法實現(xiàn)對注解中屬性對應(yīng)值的返回(自定義注解中的 value 的對應(yīng)屬性值)

 當注解的 @Retention 為 RUNTIME 時,才可以通過反射 API 獲取注解信息

Annotation[] annotations = Test.class.getAnnotations();
MyAnnotation myAnno = Test.class.getAnnotation(MyAnnotation.class);
String value = myAnno.value();
  • Class.getAnnotation(Class) 最終會調(diào)用 JVM 內(nèi)部的 native 方法,遍歷類的 RuntimeVisibleAnnotations 表。
  • 對于找到的每個注解,JVM 會動態(tài)生成一個代理對象(java.lang.reflect.Proxy)來實現(xiàn)該注解接口。
  • 這個代理對象內(nèi)部有一個 AnnotationInvocationHandler(在 sun.reflect.annotation 包下),它維護了一個 Map<String, Object>,里面存放了解析出的注解屬性名和值(例如 {“value”: “hello”})
  • 代理對象的 invoke 方法會根據(jù)注解屬性名返回對應(yīng)的值(這些值存儲在字節(jié)碼中,由 JVM 解析后保存)。
  • 因此,myAnno.value() 實際執(zhí)行的是代理對象的方法調(diào)用,而不是某個實現(xiàn)類的實例方法。

@MyAnnotation(“hello”) 本質(zhì)上是 @MyAnnotation(value = “hello”),相當于給value賦值為 “hello”,調(diào)用myAnno.value()本質(zhì)上調(diào)用代理對象的 invoke 方法,最終返回屬性值。

到此這篇關(guān)于【Java基礎(chǔ)面經(jīng)】Java 注解的底層原理的文章就介紹到這了,更多相關(guān)Java 注解原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot中@RequestBody不能和Multipart同時傳遞的問題解決

    SpringBoot中@RequestBody不能和Multipart同時傳遞的問題解決

    本文主要介紹了SpringBoot中@RequestBody不能和Multipart同時傳遞的問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • Mybatis批量插入index out of range錯誤的解決(較偏的錯誤)

    Mybatis批量插入index out of range錯誤的解決(較偏的錯誤)

    這篇文章主要介紹了Mybatis批量插入index out of range錯誤的解決(較偏的錯誤),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • mybatisplus按條件修改實體單個字段實現(xiàn)方式

    mybatisplus按條件修改實體單個字段實現(xiàn)方式

    在MyBatis-Plus中,可以使用UpdateWrapper/LambdaUpdateWrapper按條件修改實體單個字段,推薦使用LambdaUpdateWrapper,它具有類型安全、清晰、高效等優(yōu)點,避免使用updateById()或傳入實體對象的方式,通過示例展示如何正確使用UpdateWrapper進行單個字段的更新
    2026-04-04
  • Mybatis多參數(shù)及實體對象傳遞實例講解

    Mybatis多參數(shù)及實體對象傳遞實例講解

    在使用Mybatis的時候,經(jīng)常會有各種各樣的參數(shù)傳遞,不同類型,不同個數(shù)的參數(shù),下面小編通過例子給大家講解下Mybatis多參數(shù)及實體對象傳遞,一起看看吧
    2016-12-12
  • java.lang.Long cannot be cast to java.lang.Integer數(shù)據(jù)類型轉(zhuǎn)換異常解決辦法

    java.lang.Long cannot be cast to ja

    本文主要介紹了java.lang.Long cannot be cast to java.lang.Integer數(shù)據(jù)類型轉(zhuǎn)換異常解決辦法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • JVM?中的?returnAddress過程詳解

    JVM?中的?returnAddress過程詳解

    JVM的畢竟是個虛擬機,是一種規(guī)范,雖說符合馮諾依曼的計算機設(shè)計理念,但是他并不是實體計算機,所以他的組成也不是什么存儲器,控制器,運算 器,輸入輸出設(shè)備,本文給大家介紹JVM?中的?returnAddress,感興趣的朋友一起看看吧
    2022-04-04
  • SpringBoot 多線程事務(wù)回滾的實現(xiàn)

    SpringBoot 多線程事務(wù)回滾的實現(xiàn)

    本文是基于springboot的@Async注解開啟多線程,并通過自定義注解和AOP實現(xiàn)的多線程事務(wù),避免繁瑣的手動提交/回滾事務(wù),感興趣的可以了解一下
    2024-02-02
  • 學習Java之Java中的異常處理機制詳解

    學習Java之Java中的異常處理機制詳解

    在本文中,小編將帶領(lǐng)大家來學習Java的異常處理機制,包括異常機制、異常類型、如何捕獲異常、如何拋出異常以及如何創(chuàng)建自定義異常等核心內(nèi)容,感興趣的同學跟著小編一起來看看吧
    2023-08-08
  • Java使用POI實現(xiàn)導(dǎo)出Excel的方法詳解

    Java使用POI實現(xiàn)導(dǎo)出Excel的方法詳解

    在項目開發(fā)中往往需要使用到Excel的導(dǎo)入和導(dǎo)出,導(dǎo)入就是從Excel中導(dǎo)入到DB中,而導(dǎo)出就是從DB中查詢數(shù)據(jù)然后使用POI寫到Excel上。本文將利用POI實現(xiàn)導(dǎo)出Excel,需要的可以參考一下
    2022-10-10
  • SpringBoot啟動執(zhí)行sql腳本的3種方法實例

    SpringBoot啟動執(zhí)行sql腳本的3種方法實例

    在應(yīng)用程序啟動后,可以自動執(zhí)行建庫、建表等SQL腳本,下面這篇文章主要給大家介紹了關(guān)于SpringBoot啟動執(zhí)行sql腳本的3種方法,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-01-01

最新評論

兴山县| 云林县| 福贡县| 宣恩县| 比如县| 北海市| 静海县| 宣恩县| 黄梅县| 宜州市| 昭平县| 淮滨县| 信阳市| 和顺县| 宁国市| 祁连县| 平安县| 梨树县| 大石桥市| 乌拉特后旗| 全南县| 抚远县| 固安县| 友谊县| 星座| 伊宁市| 若尔盖县| 驻马店市| 工布江达县| 城步| 嘉义县| 肥东县| 钟山县| 留坝县| 洛南县| 元朗区| 延安市| 东丽区| 赞皇县| 天津市| 福州市|