Java 注解與反射(超詳細!!!)

Java 注解與反射(超詳細!!!)

文章目錄

  • Java 注解與反射(超詳細!!!)
    • 1.注解
      • 1.1內置注解
        • 1.1.1 @SuppressWarnings注解用法
      • 1.2 元注解
      • 1.3自定義注解
    • 2.反射
      • 2.1 反射的用途
      • 2.2 反射的使用方法
      • 2.3 class類型的對象使用場景1:
      • 2.4 class類型的對象使用場景2:
      • 2.5 通過反射創造對象
      • 2.6 使用反射機制獲取和調用類的構造方法,訪問私有構造方法并創建對象
      • 2.7 通過反射,訪問并使用成員方法

1.注解

1.1內置注解

注解(Annotation),也叫元數據。一種代碼級別的說明。它是JDK1.5及以后版本引入的一個特性,與類、接口、枚舉是在同一個層次。它可以聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,注釋。

例如:

@override:定義在java.lang.override 中,此注釋只適用于修辭方法,表示一個方法聲明打算
重寫超類中的另一個方法聲明

@Deprecated:定義在java.lang.Deprecated中,此注釋可以用于修辭方法,屬性,類,表示不
鼓勵程序員使用這樣的元素,通常是因為它很危險或者存在更好的選擇

@SuppressWarnings:定義在java.lang.SuppressWarnings中,用來抑制編譯時的警告信息.與前兩個注釋有所不同,你需要添加一個參數才能正確使用,這些參數都是已經定義好了的,我們選擇性的使用就好了

例如

@SuppressWarnings("all")@SuppressWarnings("unchecked")@SuppressWarnings(value={unchecked", "deprecation")
、、、

接下來,我們通過一個案例,講解一下注解是如何使用的,該如何使用。

//TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.public class Main implements Sum {public static void main(String[] args) {Main m = new Main();m.sum();m.sum1();}@Deprecated //  不建議使用的注解public void sum1() {System.out.println("nihao11111");}@Overridepublic void sum() {System.out.println("nihao");}}

在此案例中,我們通過了@Deprecated 表明這個一個不建議使用的方法。但是,這僅僅是建議,我們仍然可以使用。

1.1.1 @SuppressWarnings注解用法

@SuppressWarnings 批注允許您選擇性地取消特定代碼段(即,類或方法)中的警告。其中的想法是當您看到警告時,您將調查它,如果您確定它不是問題,

就可以添加一個 @SuppressWarnings 批注,以使您不會再看到警告。雖然它聽起來似乎會屏蔽潛在的錯誤,但實際上它將提高代碼安全性,因為它將防止您對警告無動于衷 — 您看到的每一個警告都將值得注意。

例如下面這個例子,idea會爆一個警告,上述代碼編譯通過且可以運行,但每行前面的“感嘆號”就嚴重阻礙了我們判斷該行是否設置的斷點了。這時我們可以在方法前添加@SuppressWarnings(“unused”) 去除這些“感嘆號”。

Contents of collection 'items' are updated, but never queried
package 藍橋杯國賽刷題;import java.util.ArrayList;
import java.util.List;public class commentTest01 {public static void main(String[] args) {commentTest01 CommentTest01 = new commentTest01();CommentTest01.addItems("1234");}public void addItems(String item) {List items = new ArrayList();items.add(item);}
}

1.2 元注解

元注解的作用就是負責注解其他注解,Java定義了4個標準的meta-annotation類型,他們被用來提供對其他annotation類型作說明.

這些類型和它們所支持的類在java.lang.annotation包中可以找到分別是@Target, @Retention ,@Documented , @lnherited

@Target:用于描述注解的使用范圍(即:被描述的注解可以用在什么地方)
@Retention :表示需要在什么級別保存該注釋信息,用于描述注解的生命周期
@Document:說明該注解將被包含在javadoc中
@lnherited:說明子類可以繼承父類中的該注解

1.3自定義注解

我們根據先前的注解寫法,模仿自己寫一個注解

在這里插入圖片描述

通過觀察創造注解包含以下元素@interface ,@Documented,@Retention,Target使用 @interface自定義注解時,自動繼承了java.lang.annotation.Annotation接口

@ intertace用來聲明一個注解,格式:public @ intertace 注解名{定義內容}

其中的每一個方法實際上是聲明了一個參數,方法的名稱就是參數的名稱返回值類型就是參數的類型( 返回值只能是基本類型,Class, String, enum )。可以通過default來聲明參數的默認值。如果只有一個參數成員,一般參數名為value。注解元素必須要有值,我們定義注解元素時,經常使用空字符串,O作為默認值。

自定義注解樣例:

//自定義注解
public class test03 {//注解可以顯示賦值, 如果沒有默認值,我們就必須給注解賦值//注解參數的順序隨意@MyAnnotation2(age = 18, name = "jacky")public void test() {}@MyAnnotation3("jacky")public void test2() {}
}@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation2{//注解的參數: 參數類型 + 參數名 + ();String name() default "";int age() default 0;int id() default -1;String[] schools() default {"peking university"};
}@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation3{//如果注解參數為value賦值時可以直接寫值String value();
}

在這個例子我們,我們定義了兩個注解,分別是@MyAnnotation2,@MyAnnotation3,其參數不相同。

2.反射

反射(Reflection)是一種 Java 程序運行期間動態技術,可以在運行時(runtime)檢査、修改其自身結構或行為。通過反射,程序可以訪問、檢測和修改它自己的類、對象、方法、屬性等成員

在連接數據庫中,反射的作用在于使用其特殊機制,直接調用目標類的構造方法。類如這段代碼中

Class.forName("com.mysql.jdbc.Driver");

通過反射的機制,將 com.mysql.jdbc.Driver 這個類加載到 JVM 中。觸發靜態初始化塊:MySQL 的驅動類在靜態初始化塊中會執行 DriverManager.registerDriver(new Driver()),自動向 DriverManager 注冊自己,使得后續可以通過 DriverManager.getConnection()建立數據庫連接。

2.1 反射的用途

  • 動態加載類:程序可以在運行時動態地加載類庫中的類;
  • 動態創建對象:反射可以基于類的信息,程序可以在運行時,動態創建對象實例;
  • 調用方法:反射可以根據方法名稱,程序可以在運行時,動態地調用對象的方法(即使方法在編寫程序時還沒有定義)
  • 訪問成員變量:反射可以根據成員變量名稱,程序可以在運行時,訪問和修改成員變量(反射可以訪問私有成員變量)
  • 運行時類型信息:反射允許程序在運行時,查詢對象的類型信息,這對于編寫通用的代碼和庫非常有用;

? Spring 框架使用反射來自動裝配組件,實現依賴注入;

? MyBatis 框架使用反射來創建resultType 對象,封裝數據查詢結果;

2.2 反射的使用方法

反射的第一步是獲取 Class 對象。Class 對象表示某個類的元數據,可以通過以下幾種方式獲取:

//獲取Class類型信息
public class Text02 {public static void main(String[] args) throws ClassNotFoundException {//方式1:通過類名Class stringClass1 = String.class;//方式2:通過Class類的forName()方法Class stringClass2 = Class.forName("java.lang.String");//方式3:通過對象調用getClass()方法Class stringClass3 = "".getClass();System.out.println(stringClass1.hashCode());//1604839423System.out.println(stringClass2.hashCode());//1604839423System.out.println(stringClass3.hashCode());//1604839423}}

2.3 class類型的對象使用場景1:

//Class類型的對象使用場景1
public class Text03 {public static void main(String[] args) {String json= "{\"name\":\"長安荔枝\",\"favCount\":234}";         Document doc=JSON.parseObject(json,Document.class);System.out.println(doc.getName());System.out.println(doc.getFavCount());}}

使用 JSON.parseObject 方法將 JSON 字符串解析為 Document 類的對象。在解析過程中,JSON 字符串中的數據會自動映射到 Document 類的對應字段中。

2.4 class類型的對象使用場景2:

通過 Class 對象在運行時獲取一個類的相關信息,包括類名、包名、成員變量(字段)、成員方法等。

//Class類型的對象使用場景2
//獲取豐富的類型內容
public class Text04 {public static void main(String[] args) throws ClassNotFoundException {Class clz = Class.forName("java.util.HashMap");//獲取類名System.out.println("完全限定名:"+clz.getName());System.out.println("簡單的類名:"+clz.getSimpleName());//獲取包名System.out.println("package"+clz.getPackage().getName());System.out.println();//獲取成員變量Field[] fieldArray =clz.getDeclaredFields();System.out.println("成員變量(字段)");for(Field field:fieldArray) {System.out.println(field);}System.out.println();//獲取成員方法Method[] methodArray = clz.getDeclaredMethods();System.out.println("成員方法");for(Method method:methodArray) {System.out.println(method);}	}
}
  • clz.getName() 返回類的完全限定名,包括包名,例如 "java.util.HashMap"
  • clz.getSimpleName() 返回類的簡單名稱,不包括包名,例如 "HashMap"
  • clz.getPackage().getName() 返回類所屬的包名,例如 "java.util"
  • clz.getDeclaredFields() 返回一個 Field 數組,包含了類聲明的所有字段(包括私有字段)。
  • clz.getDeclaredMethods() 返回一個 Method 數組,包含了類聲明的所有方法(包括私有方法)。

2.5 通過反射創造對象

有兩種方式通過反射創造對象分別是:

方式一:通過 Class 對象直接調用 newInstance() 方法

方式二:通過獲取構造方法(Constructor)來創建對象。

//通過反射的方式,創建對象
public class Text05 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {Class clz = Class.forName("com.apesource.demo01.Document");//方式1:直接通過Class對象,調用newInstance()方法Object objx = clz.newInstance();//相當于在執行無參構造方法//方式2:通過構造器(構造方法)//無參構造方法Constructor constructor1 = clz.getDeclaredConstructor();//獲取無參構造方法System.out.println(constructor1);Object obj1 = constructor1.newInstance();//執行構造器(構造方法),創建對象//有參構造方法Constructor constructor2 = clz.getDeclaredConstructor(String.class);//獲取有參構造方法System.out.println(constructor2);Object obj2 = constructor2.newInstance("兩京十五日");Constructor constructor3 = clz.getDeclaredConstructor(int.class);//獲取有參構造方法System.out.println(constructor3);Object obj3 = constructor3.newInstance(34);Constructor constructor4 = clz.getDeclaredConstructor(String.class,int.class);//獲取有參構造方法System.out.println(constructor4);Object obj4 = constructor4.newInstance("風起隴西",64);System.out.println(objx);System.out.println(obj1);System.out.println(obj2);System.out.println(obj3);System.out.println(obj4);}
  • newInstance() 方法是 Class 對象提供的一個方法,它調用類的無參構造方法來創建類的實例。
  • 注意:這個方法在 Java 9 以后已經被棄用,推薦使用 Constructor 對象來創建實例。
  • 通過 getDeclaredConstructor() 方法獲取 Document 類的無參構造方法,然后調用 newInstance() 方法創建實例。
  • 注意:如果類中沒有無參構造方法,調用 getDeclaredConstructor() 會拋出 NoSuchMethodException
  • 通過 getDeclaredConstructor(String.class) 獲取帶有一個 String 參數的構造方法,并傳入 "兩京十五日" 作為參數來創建對象。
  • 通過 getDeclaredConstructor(int.class) 獲取帶有一個 int 參數的構造方法,并傳入 34 作為參數來創建對象。

2.6 使用反射機制獲取和調用類的構造方法,訪問私有構造方法并創建對象

public class Text06 {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {Class clz = Class.forName("com.apesource.demo01.Document");//獲取一組構造器Constructor[] constructorArray1 = clz.getConstructors();//publicConstructor[] constructorArray2 = clz.getDeclaredConstructors();//public、private//獲取指定構造器Constructor constructor1 = clz.getConstructor();Constructor constructor2 = clz.getDeclaredConstructor(String.class);System.out.println(constructor1);System.out.println(constructor2);//調用私有構造器,必須設置它的訪問全限constructor2.setAccessible(true);//調用構造器,創建對象Object obj = constructor2.newInstance("長安三萬里");System.out.println(obj);}}
  • getConstructors() 方法返回一個包含所有公共(public)構造方法的數組。如果類中沒有 public 構造方法,則返回空數組。
  • getDeclaredConstructors() 方法返回一個包含所有聲明的構造方法的數組(包括私有的、受保護的和默認訪問級別的構造方法)。
  • getConstructor() 方法用于獲取類的無參構造方法(必須是 public 的)。如果沒有無參構造方法或者不是 public,則拋出 NoSuchMethodException
  • getDeclaredConstructor(Class<?>... parameterTypes) 方法用于獲取指定參數類型的構造方法。這里通過傳入 String.class 參數獲取一個帶有 String 參數的構造方法。這個構造方法可以是任何訪問級別(publicprivateprotected、默認)。
  • setAccessible(true) 用于繞過 Java 訪問控制機制,使私有構造方法也可以被調用。如果不設置 Accessibletrue,那么調用私有構造方法時會拋出 IllegalAccessException
  • newInstance(Object... initargs) 方法使用指定的構造方法創建對象。這里調用了帶有 String 參數的構造方法,并傳入 "長安三萬里" 作為參數。

2.7 通過反射,訪問并使用成員方法

public class Text08 {public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException {//硬編碼的方式
//		Document doc1 = new Document();
//		doc1.setName("海底兩萬里");
//		doc1.setFavCount(10025);//反射的方式Class clz = Class.forName("com.apesource.demo01.Document");//獲取類型信息Object doc1 = clz.newInstance();//創建對象//獲取指定名稱和參數類型的方法Method setNameMethod = clz.getMethod("setName", String.class);Method setFavCountMethod = clz.getMethod("setFavCount", int.class);//執行方法//doc1.setName("海底兩萬里");setNameMethod.invoke(doc1, "海底兩萬里");//doc1.setFavCount(10025);setFavCountMethod.invoke(doc1, 10025);System.out.println(doc1);}}
  • getMethod(String name, Class<?>... parameterTypes) 方法用于獲取類的某個 public 方法。方法名稱和參數類型必須匹配才能成功獲取方法。
  • invoke(Object obj, Object... args) 方法用于調用指定的實例方法。
  • setNameMethod.invoke(doc1, "海底兩萬里"); 等同于 doc1.setName("海底兩萬里");
  • setFavCountMethod.invoke(doc1, 10025); 等同于 doc1.setFavCount(10025);

以上便是Java注解與反射的全部內容了,筆者編寫不易,懇請點贊收藏,歡迎評論區交流!!!

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

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

相關文章

用nz-tabel寫一個合并表格

用nz-tabel寫一個合并表格 <nz-table #basicTable [nzData]"tableSearchStatus.dataList" nzBordered><thead><tr><th>班級</th><th>姓名</th><th>年齡</th><th>電話</th></tr></thead&…

第6章 放大電路的反饋

本章基本要求 會判&#xff1a;判斷電路中有無反饋及反饋的性質 會算&#xff1a;估算深度負反饋條件下的放大倍數 會引&#xff1a;根據需求引入合適的反饋 會判振消振&#xff1a;判斷電路是否能穩定工作&#xff0c;會消除自激振蕩。 6.1 反饋的概念及判斷 一、反饋的…

ansible template 文件中如果包含{{}} 等非ansible 變量處理

在 Ansible 模板中&#xff0c;如果你的 Python 腳本里有大量 {}、f""、或者其他 Jinja 會誤解析的語法&#xff0c;就需要用 {% raw %}…{% endraw %} 把它們包起來&#xff0c;只在需要替換變量的那一行單獨“放行”。例如&#xff1a; {% raw %} #!/usr/bin/env …

STM32G4 電機外設篇(一) GPIO+UART

目錄 一、STM32G4 電機外設篇&#xff08;一&#xff09; GPIOUART1 GPIO1.1 STM32CUBEMX 配置以及Keil代碼1.2 代碼和實驗現象 2 UART2.1 STM32CUBEMX 配置以及Keil代碼2.2 代碼和實驗現象 附學習參考網址歡迎大家有問題評論交流 (* ^ ω ^) 一、STM32G4 電機外設篇&#xff0…

Kotlin 中集合遍歷有哪幾種方式?

1 for-in 循環&#xff08;最常用&#xff09; val list listOf("A", "B", "C") for (item in list) {print("$item ") }// A B C 2 forEach 高階函數 val list listOf("A", "B", "C") list.forEac…

尚硅谷redis7 99 springboot整合redis之連接集群

6381宕機&#xff0c;手動shutdown后在redis中&#xff0c;634自動上位變成master結點。 但是在springboot中卻沒有動態感知道redisCluster的最新集群消息&#xff0c;所以找不到我們要檢索的數據。原因是&#xff1a;SpringBoot 2.X版本,Redis默認的連接池采用 Lettuce&#…

AI 的早期萌芽?用 Swift 演繹約翰·康威的「生命游戲」

文章目錄 摘要描述題解答案題解代碼分析示例測試及結果時間復雜度空間復雜度總結 摘要 你有沒有想過&#xff0c;能不能通過簡單的規則模擬出生與死亡&#xff1f;「生命游戲」正是這樣一種充滿魅力的數學模擬系統。這篇文章我們來聊聊它的規則到底有多神奇&#xff0c;并用 S…

web ui自動化工具playwright

playwright是微軟開源的一款web ui自動化工具&#xff0c;該工具有很多亮點&#xff0c;解決以前困擾web UI自動化測試的很多難點。這篇博客將介紹playwright主要特點。 playwright支持錄制減少了編寫成本 如果要使用playwright的錄制功能&#xff0c;有兩種途徑&#xff0c;途…

移動安全Android——客戶端靜態安全

一、反編譯保護 測試工具 Jadx GitHub - skylot/jadx: Dex to Java decompiler PKID [下載]PKID-APP查殼工具-Android安全-看雪-安全社區|安全招聘|kanxue.com 測試流程 &#xff08;1&#xff09;通過Jadx對客戶端APK文件進行反編譯&#xff0c;觀察是否進行代碼混淆 &…

04-redis-分布式鎖-edisson

1 基本概念 百度百科&#xff1a;控制分布式系統之間同步訪問共享資源方式。 在分布式系統中&#xff0c;常常需要協調他們的動作。如果不同的系統或是同一個系統的不同主機之間共享了一個或一組資源&#xff0c;那么訪問這些資源的時候&#xff0c;往往需要互斥來防止…

cf每日刷題

目錄 String&#xff08;800&#xff09; Skibidus and Amogu&#xff08;800&#xff09; Apples in Boxes&#xff08;1100&#xff09; String&#xff08;800&#xff09; https://codeforces.com/problemset/problem/2062/A #include <iostream> #include <…

AWS WebRTC:獲取ICE服務地址(part 1)

建立WebRTC連接的第二步是獲取ICE服務地址。 ICE全稱&#xff1a;Interactive Connectivity Establishment&#xff0c;建立互動連接。 ICE 服務地址&#xff0c;主要是 TURN 和 STUN 服務器的地址&#xff0c;用于 WebRTC 在 NAT 網絡環境中協商建立連接。 上代碼&#xff…

Python興趣匹配算法:從理論到實戰的進階指南

目錄 一、興趣匹配算法的技術棧解析 1. 基礎特征匹配階段 2. 向量空間模型階段 3. 深度學習階段 二、工程化實踐關鍵技術 1. 特征工程體系 2. 相似度計算優化 三、典型應用場景實現 1. 社交好友推薦系統 2. 電商商品推薦系統 四、性能優化與挑戰應對 1. 計算性能優…

【C語言】講解 程序分配的區域(新手)

目錄 代碼區 數據區 堆區 棧區 常量區 重點比較一下堆區與 棧區 總結&#xff1a; 前言&#xff1a; C語言程序的內存分配區域是理解其運行機制的重要部分。根據提供的多條證據&#xff0c;我們可以總結出C語言程序在運行時主要涉及以下五個關鍵內存區域&#xff1a; 代…

Go語言之接口與多態 -《Go語言實戰指南》

接口是 Go 語言實現 多態 的核心機制。本章將幫助你理解接口的設計哲學、動態行為&#xff0c;以及它如何讓 Go 實現面向接口編程的能力。 一、什么是接口&#xff1f; 接口是一組方法簽名的集合&#xff0c;任何類型只要實現了接口中聲明的所有方法&#xff0c;就被視為實現了…

JSR 303(即 Bean Validation)是一個通過??注解在 Java Bean 上定義和執行驗證規則??的規范

&#x1f6e0;? 一、JSR 303是什么&#xff1f; JSR 303&#xff08;Java Specification Requests 303&#xff09;是Java EE 6的子規范&#xff0c;全稱??Bean Validation??。它通過注解方式對JavaBean的屬性值進行標準化校驗&#xff0c;例如檢查非空、長度、格式等規則…

【圖像處理入門】3. 幾何變換基礎:從平移旋轉到插值魔法

摘要 掌握圖像的幾何變換相當于學會「圖像的空間魔法」。本文將帶你理解平移/旋轉/縮放的數學原理&#xff0c;掌握OpenCV中warpAffine和getAffineTransform的核心用法&#xff0c;對比最近鄰、雙線性等插值算法的優劣。通過圖像翻轉、鏡像、透視變換實戰&#xff0c;學會用變…

微信小程序學習目錄

個人簡介 &#x1f468;?&#x1f4bb;?個人主頁&#xff1a; 魔術師 &#x1f4d6;學習方向&#xff1a; 主攻前端方向&#xff0c;正逐漸往全棧發展 &#x1f6b4;個人狀態&#xff1a; 研發工程師&#xff0c;現效力于政務服務網事業 &#x1f1e8;&#x1f1f3;人生格言&…

QT 5.15.2 程序中文亂碼

1. 在.pro文件中添加&#xff1a; msvc { QMAKE_CXXFLAGS /source-charset:utf-8 /execution-charset:utf-8 }備注&#xff1a;.pro文件只有在選擇 qmake 方式才會生成。 [Cmake 只會生成 CMakeLists.txt 文件] 2. 在文件首部增加以下程序行 #pragma execution_character_s…

Unity UI設計優化與模式原則

前言 在 Unity 中設計高效且可維護的 UI 系統時&#xff0c;需要結合性能優化和設計模式兩大核心方向。以下是關鍵原則及實踐方法&#xff1a; 對惹&#xff0c;這里有一個游戲開發交流小組&#xff0c;希望大家可以點擊進來一起交流一下開發經驗呀&#xff01; 一、UI 性能…