Java基礎-注解

注解

    • 注解是用來干什么的
    • 它有什么作用
    • 注解的常見分類
    • 內置注解
      • @Override
        • 注解定義
      • @Deprecated
        • 注解定義
      • @SuppressWarnings
        • 注解定義
    • 元注解
      • @Target
        • 注解定義
        • ElementType
      • @Retention&&@RetentionTarget
        • 注解定義
        • RetentionPolicy
      • @Documented
        • 注解定義
      • @Inherited
        • 注解定義
        • 用法
      • Repeatable(重復注解)
        • 注解定義
        • JDK8之前
        • JDK8之后
      • Native
    • 注解與反射接口
        • 相關接口
    • 自定義注解
    • 注解的本質(未完結)

注解是用來干什么的

注解的漢語意思: 用淺近的文字解釋艱深的詞句

注解是JDK1.5版本開始引入的一個特性,用于對代碼進行說明,可以對包,類,接口,字段,方法參數,局部變量進行注解.

它有什么作用

主要作用是下面四個方面

  • 生成文檔
    通過代碼里標識的元數據生成javaDoc文檔
  • 編譯檢查
    通過代碼里標識的元數據讓編譯器在編譯期間進行檢查驗證
  • 編譯時動態處理
    編譯時通過代碼里標識的元數據動態處理,例如動態生成代碼
  • 運行時動態處理
    運行時通過底阿媽里標識的元數據動態處理,例如使用反射注入實例

注解的常見分類

  • Java自帶的標準注解
    用于標明重寫某個方法,某個類或方法過時,表明要忽略的警告,用這些注解表明后編譯器就會 進行檢查
  • 元注解
    用于定義注解的注解
  • 自定義注解
    根據自己的需求定義注解,并可用元注解對自定義注解進行注解

內置注解

@Override

表示當前的方法定義將覆蓋父類中的方法

注解定義
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

這個注解可以用來修飾方法,并只在編譯期有效,編譯期后class文件就不存在了

@Deprecated

表示代碼被棄用,如果使用了被@Deprecated注解的代碼編譯器會發出警告

注解定義
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
  1. 它會被文檔化
  2. 可以保留到運行時
  3. 可以修飾構造方法,屬性,局部變量,方法,包,參數,類型

@SuppressWarnings

關閉編譯器警告信息

注解定義
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {String[] value();
}
  1. 可以修飾類型,屬性,方法,參數,構造器,局部變量
  2. 只能存活在源碼
  3. 取值為String[]
    它可以取的值如下所示:
參數作用
all抑制所有警告
deprecation抑制啟用注釋的警告
finally抑制finally模塊沒有返回的警告
null忽略對null的操作
unused抑制沒被使用過的代碼的警告
等等

元注解

@Target

描述注解的使用范圍(即被修飾的注解可以在什么地方使用)

注解定義
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {/*** Returns an array of the kinds of elements an annotation interface* can be applied to.* @return an array of the kinds of elements an annotation interface* can be applied to*/ElementType[] value();
}
  1. 可被文檔化
  2. 可以保留到運行時
  3. 只能在注解類上使用
  4. value值在ElementType中
ElementType
public enum ElementType {TYPE, // 類、接口、枚舉類FIELD, // 成員變量(包括:枚舉常量)METHOD, // 成員方法PARAMETER, // 方法參數CONSTRUCTOR, // 構造方法LOCAL_VARIABLE, // 局部變量ANNOTATION_TYPE, // 注解類PACKAGE, // 可用于修飾:包TYPE_PARAMETER, // 類型參數,JDK 1.8 新增TYPE_USE // 使用類型的任何地方,JDK 1.8 新增}

@Retention&&@RetentionTarget

描述注解保留的時間范圍(即被描述的注解在它所修飾的類中可以被保留到何時)

注解定義
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {RetentionPolicy value();
}
  1. 可被文檔化
  2. 可以保留到運行時
  3. 只能在注解類上使用
  4. value值在RetentionPolicy 中
RetentionPolicy
public enum RetentionPolicy {SOURCE,    // 源文件保留CLASS,       // 編譯期保留,默認值RUNTIME   // 運行期保留,可通過反射去獲取注解信息
}

我們可以通過執行javap -verbose RetentionTest獲取到RetentionTest的class字節碼內容如下.

{public retention.RetentionTest();flags: ACC_PUBLICCode:stack=1, locals=1, args_size=10: aload_01: invokespecial #1                  // Method java/lang/Object."<init>":()V4: returnLineNumberTable:line 3: 0public void sourcePolicy();flags: ACC_PUBLICCode:stack=0, locals=1, args_size=10: returnLineNumberTable:line 7: 0public void classPolicy();flags: ACC_PUBLICCode:stack=0, locals=1, args_size=10: returnLineNumberTable:line 11: 0RuntimeInvisibleAnnotations:0: #11()public void runtimePolicy();flags: ACC_PUBLICCode:stack=0, locals=1, args_size=10: returnLineNumberTable:line 15: 0RuntimeVisibleAnnotations:0: #14()
}

我們可以得到下面的兩個結論:

  1. 編譯期沒有記錄下sourcePolicy()方法的注解信息
  2. 編譯期分別使用了RuntimeInvisibleAnnotations, RuntimeVisibleAnnotations 屬性去記錄了classPolicy()方法和runtimePolicy()方法的注解信息

@Documented

描述使用javaDoc工具為類生成幫助文檔時是否要保留其注解信息

注解定義
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestDocAnnotation {public String value() default "default";
}
  1. 可被生成文檔
  2. 使用范圍是類,接口,枚舉類,成員方法

@Inherited

被他修飾的注解具有繼承性.
如果某個類使用了被@Inherited修飾的注解,則其子類將自動具有該注釋

注解定義
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
  1. 可被生成文檔
  2. 可被保留到運行時
  3. 只能用于注解類
用法

定義@Inherited注解

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestInheritedAnnotation {String [] values();int number();
}

使用這個注解

@TestInheritedAnnotation(values = {"value"}, number = 10)
public class Person {
}class Student extends Person{@Testpublic void test(){Class clazz = Student.class;Annotation[] annotations = clazz.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation.toString());}}
}

輸出內容

xxxxxxx.TestInheritedAnnotation(values=[value], number=10)

即使Student類沒有顯示地被注解@TestInheritedAnnotation,但是它的父類Person被注解,而且@TestInheritedAnnotation@Inherited注解,因此Student類自動有了該注解.

Repeatable(重復注解)

允許在同一申明類型(類,屬性,方法)多次使用同一注解

注解定義
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {Class<? extends Annotation> value();
}
  1. 可被生成文檔
  2. 可以保留至運行時
  3. 只能作用域注解類
JDK8之前

JDK8之前有重復使用注解的解決方案,但是可讀性不好
方案: 由另一個注解來存儲重復注解,在使用的時候,用存儲注解Authorities來擴展重復注解

public @interface Authority {String role();
}public @interface Authorities {Authority[] value();
}public class RepeatAnnotationUseOldVersion {@Authorities({@Authority(role="Admin"),@Authority(role="Manager")})public void doSomeThing(){}
}
JDK8之后

方案: 創建重復注解時,加上@Repeatable,指向存儲注解Authorities,在使用的時候,可以直接重復使用Authority注解.

@Repeatable(Authorities.class)
public @interface Authority {String role();
}public @interface Authorities {Authority[] value();
}public class RepeatAnnotationUseNewVersion {@Authority(role="Admin")@Authority(role="Manager")public void doSomeThing(){ }
}

Native

使用@Native注解修飾成員變量,表示這個變量可以被本地代碼引用,常常被代碼生成工具使用,了解即可.

注解與反射接口

我們如果想自定義注解,那么就必須先了解注解與反射接口的這部分內容.
反射包java.lang.reflect下的AnnotatedElement接口提供這些方法.
注意:只有注解被定義為RUNTIME后,該注解才能是運行時可見,當class文件被裝載時,被保存在class文件中的Annotation才會被虛擬機讀取.

AnnotatedElement接口是所有程序元素(Class,Method,Constructor)的父接口.

Classpublic final class Class<T> implements Serializable, GenericDeclaration, Type, AnnotatedElement, TypeDescriptor.OfField<Class<?>>, Constable {
xxxx
}
Methodpublic final class Method extends Executable {
xxx
}
public abstract sealed class Executable extends AccessibleObject{
xxx
}
public class AccessibleObject implements AnnotatedElement {
xxx
}Constructorpublic final class Constructor<T> extends Executable {
xxx
}
和上面Method的繼承路徑是是一樣的,不贅述了.
相關接口
  • boolean isAnnotationPresent(Class<?extends Annotation> annotationClass)
    判斷該元素上是否包含指定類型的注解,存在則返回true,否則返回false.
    (此方法會忽略注解對應的注解容器)
  • <T extends Annotation> T getAnnotation(Class<T> annotationClass)
    返回該程序元素上存在的,制定類型的注解,如果該類型的注解不存在,則返回null
  • <Annotation[] getAnnotations()
    返回該程序元素上存在的所有注解,若沒有注解,返回長度為0的數組
  • <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
    返回該程序元素上存在的,指定類型的注解數據.若沒有,返回長度為0的數組
    該方法調用者可以隨意修改返回數據,不會對其他調用者返回數組產生影響.
    (會檢測注解對應的重復注解容器)
  • <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass
    返回直接存在此元素上的所有注解.
    該方法忽略繼承的注解,如果沒有注解直接存在此元素上,返回null.
  • <T extends Annotation> T[] getDeclaredAnotationsByType(Class<T> annotationClass)
    返回直接存在此元素上所有指定類型注解,
    該方法忽略繼承的注解
  • Annotion[] getDeclaredAnnotations()
    返回直接存在于此元素上的所有注解機器注解對應的重復注解容器.
    該方法忽略繼承注解,如果沒有注釋直接存在于此元素上,則返回長度為零的一個數組。該方法的調用者可以隨意修改返回的數組,而不會對其他調用者返回的數組產生任何影響。

自定義注解

理解注解與反射接口后,我們通過自定義注解來把知識點融合應用一下

  • 定義注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMethodAnnotation {public String title() default "";public String description() default "";}
  • 使用注解
public class TestMethodAnnotation {@Override@MyMethodAnnotation(title = "toStringMethod", description = "override toString method")public String toString() {return "Override toString method";}@Deprecated@MyMethodAnnotation(title = "old static method", description = "deprecated old static method")public static void oldMethod() {System.out.println("old method, don't use it.");}@SuppressWarnings({"unchecked", "deprecation"})@MyMethodAnnotation(title = "test method", description = "suppress warning static method")public static void genericsTest() throws FileNotFoundException {List l = new ArrayList();l.add("abc");oldMethod();}
}
  • 用反射接口獲取注解信息
public static void main(String[] args) {try {// 獲取所有methodsMethod[] methods = TestMethodAnnotation.class.getClassLoader().loadClass(("com.pdai.java.annotation.TestMethodAnnotation")).getMethods();// 遍歷for (Method method : methods) {// 方法上是否有MyMethodAnnotation注解if (method.isAnnotationPresent(MyMethodAnnotation.class)) {try {// 獲取并遍歷方法上的所有注解for (Annotation anno : method.getDeclaredAnnotations()) {System.out.println("Annotation in Method '"+ method + "' : " + anno);}// 獲取MyMethodAnnotation對象信息MyMethodAnnotation methodAnno = method.getAnnotation(MyMethodAnnotation.class);System.out.println(methodAnno.title());} catch (Throwable ex) {ex.printStackTrace();}}}} catch (SecurityException | ClassNotFoundException e) {e.printStackTrace();}
}
  • 測試的輸出
Annotation in Method 'public static void com.pdai.java.annotation.TestMethodAnnotation.oldMethod()' : @java.lang.Deprecated()
Annotation in Method 'public static void com.pdai.java.annotation.TestMethodAnnotation.oldMethod()' : @com.pdai.java.annotation.MyMethodAnnotation(title=old static method, description=deprecated old static method)
old static method
Annotation in Method 'public static void com.pdai.java.annotation.TestMethodAnnotation.genericsTest() throws java.io.FileNotFoundException' : @com.pdai.java.annotation.MyMethodAnnotation(title=test method, description=suppress warning static method)
test method
Annotation in Method 'public java.lang.String com.pdai.java.annotation.TestMethodAnnotation.toString()' : @com.pdai.java.annotation.MyMethodAnnotation(title=toStringMethod, description=override toString method)
toStringMethod

注解的本質(未完結)

這部分要扯到動態代理和注解的處理器,emmm比較麻煩.
后面發完動態處理后返回來填坑

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/696143.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/696143.shtml
英文地址,請注明出處:http://en.pswp.cn/news/696143.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

低代碼開發:推動互聯網企業數字化轉型的關鍵因素

聯網行業作為我國數字經濟發展的核心驅動力&#xff0c;在推動國家數字化轉型中扮演著至關重要的角色。與其他傳統行業相比&#xff0c;互聯網企業面臨更加緊迫的數字化轉型需求&#xff0c;因為它們需要不斷適應快速變化的市場環境和技術趨勢。 然而&#xff0c;由于互聯網企業…

深入理解APDU協議與Java開發

1. 什么是APDU&#xff1f; APDU&#xff0c;即應用協議數據單元&#xff08;Application Protocol Data Unit&#xff09;&#xff0c;是一種在智能卡與卡片讀卡器之間進行通信的協議。APDU定義了在交互中傳輸的數據格式和規則&#xff0c;允許讀卡器發送指令并接收響應。 2…

MFC 皮膚庫配置

1.創建MFC 對話框 2.添加皮膚資源 添加資源 添加頭文件 關閉SDL檢測 添加靜態庫文件 修改字符集 添加頭文件 將皮膚中的ssk文件加載到初始化實例中 > 運行即可

springboot 的 websocket 里面使用 @Autowired 注入 service 或 bean 時,報空指針異常

直接上解決方案&#xff1a; 在你的WebSocketServer服務器中 public static MessageService messageService; //要注入的類// 注入的時候&#xff0c;給類的 service 注入Autowiredpublic void setChatService(MessageService messageService) {WebSocketServer.messageSer…

【寸鐵的刷題筆記】樹、dfs、bfs、回溯、遞歸(一)

【寸鐵的刷題筆記】樹、dfs、bfs、回溯、遞歸(一) 大家好 我是寸鐵&#x1f44a; 總結了一篇刷題關于樹、dfs、bfs、回溯、遞歸的文章? 喜歡的小伙伴可以點點關注 &#x1f49d; 105. 從前序與中序遍歷序列構造二叉樹 模擬分析圖 代碼實現 /*** Definition for a binary tre…

HarmonyOS—添加/刪除Module

Module是應用/服務的基本功能單元&#xff0c;包含了源代碼、資源文件、第三方庫及應用/服務配置文件&#xff0c;每一個Module都可以獨立進行編譯和運行。一個HarmonyOS應用/服務通常會包含一個或多個Module&#xff0c;因此&#xff0c;可以在工程中創建多個Module&#xff0…

如何利用內網穿透工具在企業微信開發者中心實現本地接口服務回調

文章目錄 1. Windows安裝Cpolar2. 創建Cpolar域名3. 創建企業微信應用4. 定義回調本地接口5. 回調和可信域名接口校驗6. 設置固定Cpolar域名7. 使用固定域名校驗 企業微信開發者在應用的開發測試階段&#xff0c;應用服務通常是部署在開發環境&#xff0c;在有數據回調的開發場…

SQL查詢每個類別價格前3的數據

SELECTproduct_id,category,price FROM (SELECTproduct_id,category,price,ROW_NUMBER() OVER (PARTITION BY category ORDER BY price) AS rankFROMyour_products_table ) AS ranked_products WHERErank < 3;DENSE_RANK() 和 ROW_NUMBER() 是窗口函數&#xff08;Window Fu…

前端知識復習

1.symbol類型 Symbol 是 ECMAScript 6 中引入的一種新的基本數據類型&#xff0c;它表示獨一無二的值。Symbol 值是通過 Symbol() 函數創建的。 Symbol 值具有以下特點&#xff1a; 獨一無二性&#xff08;唯一性&#xff09;&#xff1a;每個通過 Symbol() 函數創建的 Symb…

十三:集合

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 01、Java 集合框架概述1.1、集合框架與數組的對比及概述1.2、集合框架涉及到的API 02、Collection接口方法2.1、Collection接口中的常用方法12.2、Collection接口中…

在idea中配置Tomcat

1.在idea中點擊右上角 2.點擊Edit Configurations,點擊加號 3.向下拉找到Tomcat Server下的Local,點一下 點擊Configure 找到tomcat文件路徑,選擇apache-tomcat-8.5.63(8.5.63是我的版本號) 選擇好路徑后點ok就配置好了 總步驟:

Vue 圖片輪播第三方庫 Vue-awesome-swiper介紹及簡單例子

vue-awesome-swiper 是一個基于 Swiper 的 Vue 輪播圖組件&#xff0c;Swiper 是一個流行的移動端觸摸滑動插件。它為 Vue.js 應用提供了一套豐富的輪播組件&#xff0c;支持多種布局和功能&#xff0c;如自動播放、無限循環、觸摸滑動等。 安裝 首先&#xff…

代碼隨想錄算法訓練營第一天

● 今日學習的文章鏈接和視頻鏈接 ● 自己看到題目的第一想法 1. 704二分法&#xff1a; 方法一&#xff1a; 整個數組是 左閉右閉區間 [ ] left指針指向數組開始下標&#xff0c; right 指針指向數組最后下表nums.size()-1, mid為 (leftright) /2循環條件 left<rightnu…

打開stable diffusion webui時,提示缺少clip或clip安裝不上的解決方案(windows下的操作)

1.問題描述 打開stable diffusion webui時&#xff0c;提示缺少clip或clip安裝不上 2.解決方案 原因&#xff1a;stable diffusion webui環境中的clip其實是open_clip&#xff0c;不能用pip install clip安裝解決方法是直接到github下載 open_clip 代碼到本地&#xff0c;并…

linux環境ssh-rsa進行簽名\權限\登錄\原理(免密登錄)

linux環境ssh-rsa進行簽名權限登錄(免密登錄) SSH原理與運用什么是SSH?SSH的使用場景ssh-rsa獲取xshell環境登錄獲取ssh-rsa使用ssh-rsa登錄SHA系列SHA-1、SHA-256和RSA的區別RSA原理數論基礎RSA機制RSA數學密鑰生成公式RSA數學加密理論RSA數學簽名公式

小折疊也能成為主力機,全新小折疊旗艦華為Pocket 2正式發布

2024年2月22日&#xff0c;華為在三亞舉辦華為Pocket 2時尚盛典&#xff0c;正式發布其全新小折疊旗艦華為Pocket 2。一直以來&#xff0c;華為致力于萃取各界藝術靈感&#xff0c;不斷探尋科技美學的可能性&#xff0c;華為Pocket系列更是秉承將奢雅美學與尖端科技融為一體的理…

探索Redis是否為單線程的奧秘(文末送書)

&#x1f308;個人主頁&#xff1a;聆風吟 &#x1f525;系列專欄&#xff1a;數據結構、網絡奇遇記 &#x1f516;少年有夢不應止于心動&#xff0c;更要付諸行動。 文章目錄 &#x1f4cb;前言一. Redis中的多線程二. I/O多線程三. Redis中的多進程四. 結論五. 書籍推薦5.1 書…

高效時間管理法則

你是否天天在忙&#xff0c;是否忙的不得要領&#xff0c;認真領會時間管理的四象限工作法&#xff0c;它會讓你的工作變得高效。 目錄 一、時間管理的誤區 二、時間是如何被浪費的&#xff1f; 內部因素 外部因素 三、時間管理的5個階段 1.公雞型時間管理&#xff1a; …

第一個Qt程序中的秘密

創建第一個程序 首先我們打開Qt Creator 打開文件->New Projects... 菜單&#xff0c;創建我們的第一個Qt項目 選擇 Qt Widgets Application&#xff0c;點擊選擇...按鈕 之后&#xff0c;輸入項目名稱QtLearning&#xff0c;并選擇創建路徑&#xff0c; 在build system中選…

ConnectWise ScreenConnect 身份驗證繞過漏洞復現可RCE(CVE-2024-1709)

0x01 產品簡介 ConnectWise ScreenConnect ,是一款自托管的遠程桌面軟件應用,該款軟件允許用戶自行托管,可以在自己的服務器、個人電腦、虛擬機或虛擬專用服務器上運行。 0x02 漏洞概述 ConnectWise ScreenConnect低于23.9.8 版本的產品中,SetupWizard.aspx接口處存在身…