關于Java 反射的簡單易懂的介紹

目錄

#0.總覽

#1.?類的反射

①介紹

②獲取

③作用

獲取構造函數:

創建實例:

字段操作:?? ? ?

方法操作:

獲取修飾符:

#2.總結?


#0.總覽

反射,官方是這樣介紹它的:

Reflection is a feature in the Java programming language. It allows an executing Java program to examine or "introspect" upon itself, and manipulate internal properties of the program.

翻譯過來就是:反射是 Java 編程語言中的一項功能。它允許正在執行的 Java 程序檢查或“內省”自身,并作程序的內部屬性。

再翻譯成人話就是:反射可以讓程序可以把本身的各種方法,參數當作變量來使用。?

為什么翻譯成“反射”?因為這個過程就像是照鏡子:程序通過照鏡子知道自己有什么方法和參數。

詳細的說,有:

  • 獲取類的信息(類名、方法、字段、構造方法等)。
  • 創建類的實例。
  • 調用類的方法、修改字段的值。
  • 動態地加載類和進行方法調用。
  • 與代理息息相關

#1.?類的反射

①介紹

? ? ? ? 首先得介紹一下Class類

Class類是反射的核心部分

Class類和真實的類對象不是一個東西!Class類只是包含了對應類關于其涉及反射的一系列操作的類。每個類都會有屬于自己的Class對象:

列如 String.class? ? ? ? ? ? ?Integer.class等

嘗試輸出:

System.out.println(String.class);

會得到?class java.lang.String

這是類的全限定類名,可以看成是類的標識。

②獲取

通過一些方法,我們能獲得一個類的Class對象:

Class ex1 = Class.forName("java.lang.String");

Class ex2 =?String.class;

String string = new String();
Class ex3 =?string.getClass();

那獲取到Class類有什么用呢??

③作用

獲取構造函數:

拿這個類來舉例:

public class Temp {public int a;public int b;private int c = 10;public Temp() {}public Temp(int a) {this.a = a;}private Temp(int a, int b) {this.a = a;this.b = b;}public void sing(){System.out.println("ahhhhhh!");}private void dance(){System.out.println("haaaaaa!");}
}
Class ex = Temp.class;

ex.getConstructor();? ? ex.getConstructor(int.class);? ? ? ? ?

這會獲得其一個指定的公共構造方法,注意!括號中的參數要這樣寫上對應的Class類才能獲取到!

ex.getDeclaredConstructor();則可以獲取到所有構造方法

相對的,Constructor<?>[] constructors =?ex.getConstructors();則會獲取所有公用構造方法

getDeclaredConstructors同理

? ? ? ?


創建實例:

Constructor constructor = ex.getConstructor(int.class);
Temp obj = (Temp) constructor.newInstance( 30);

這樣就根據指定的構造方法創建出了一個指定的實例

? ? ? ?


字段操作:?

Temp obj = (Temp) constructor.newInstance( 30);
Field field = ex.getField("a");
System.out.println(field);
int value = field.getInt(obj);?
System.out.println(value);

這里會輸出 30

注意!除了getInt還有getchar等對應基本數據類型,其他的統一為get()

但其實get()也能處理基本數據類型

格式為?Field.get(已實例化的對象)

對于私有變量,無獨有偶:getDeclaredField(“c”)即可

但是只能System.out.println(field);,即獲取全限定字段名,無法獲得具體值!

解決方法在下:

但是對于字段修改:?

如果是公共字段:

field.set(obj, 666);?

就可以完成修改

私有字段是無法修改的!

必須先取消限制:

field.setAccessible(true);

這樣才可以讓私有字段像公共字段一樣可以被查看,修改。


? ? ? ? ?

方法操作:

對于方法,有了前面的鋪墊則簡單得多:

對于公共方法:

Class ex = Temp.class;
Constructor constructor = ex.getConstructor();
Temp obj = (Temp) constructor.newInstance();

Method greetMethod = ex.getMethod("sing");
greetMethod.invoke(obj);?

這樣就成功執行了sing方法

如果想要獲取所有方法

Method[] methods =?ex.getMethods();即可

但是必須要有一個已經實例化的對象obj才能正常的通過invoke操作來執行方法!

實際上,執行的方法實際上是已經實例化的obj里面對應的方法!

對于一些函數,可能名字相同但是參數不同,可以仿照構造函數那樣加以區分:

Method greetMethod = ex.getMethod("sing",int.class);

Method greetMethod = ex.getMethod("sing",String.class);類似這樣來區分

對于私有方法:?

和字段一模一樣

在方法名上加上Declared

getDeclaredMethod,getDeclaredMethods

然后得加上greetMethod.setAccessible(true);才能正常操作


獲取修飾符:

可以通過類似于:

int x = greetMethod.getModifiers();

來獲取任何方法/字段的修飾符,也許你會疑惑為什么是int類型,原因是JAVA中的確是用數字來存儲修飾符的,比如說:

public = 1,?private = 2protected = 3,default= 4


?獲取接口:

獲取接口相對來說非常簡單:

Class<?>[] interfaces =?ex.getInterfaces();

這樣便可獲取所有ex類所實現的接口


獲取注釋:

Annotation[] annotations = ex.getAnnotations();

這樣就獲取了ex類所有的注釋內容!

如果想獲取方法的注釋也非常簡單:

Annotation[] annotations = ex.getMethod("xxx").getAnnotations();

(提一句,對于每個注釋都是一個單獨的類型,假如你需要@CY注釋,改成
CY?annotation?= ex.getMethod("xxx").getAnnotation();也行)

接下來想要提取注釋變量什么的就隨你了

這種方法可以用來實現公共字段補全


#2.總結?

? ? ? ? 歸功于反射機制,程序得以對本身進行修改而不依賴于人工修改,也提供了更多的靈活性,

更是為實現動態代理提供了可能。

(我也寫了一篇介紹代理的文章,歡迎捧場!)

你也許會發現,這種獲取參數,接口,方法是不是很熟悉?是不是我們用的IDE就有點用了這種方式的意思?不然為什么我們寫了一個函數就能提示要放什么參數進去?

這的確很像,但實際上IDE是會實時構造一個抽象語法樹(AST),它是代碼結構的表示。這使得 IDE 能夠理解類、方法、字段和參數的存在及其類型。

盡管如此,反射非常重要,java,spring框架里面反射無處不在,

但是,反射的性能開銷很大,因為它要在運行中實時解析類,方法,字段,這些原本是在編譯時完成的,而且反射無法被編譯器進行優化!

所以謹慎使用!

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

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

相關文章

【精調】LLaMA-Factory 快速開始1: Meta-Llama-3.1-8B-Instruct

llamafactory-cli train examples/train_lora/llama3_lora_sft.yaml llamafactory-cli chat examples/inference/llama3_lora_sft.yaml llamafactory-cli export examples/merge_lora/llama3_lora_sft.yaml模型下載 git clone https://www.modelscope.cn/LLM-Research/Meta-Lla…

【07】區塊鏈性能

7-1 基礎性能優化 7-1-1 區塊鏈性能瓶頸 總述 區塊鏈性能指標 區塊鏈的性能指標主要包括&#xff1a; 吞吐量&#xff1a;在固定時間內處理的交易數量 延時&#xff1a;對交易的響應和處理時間 主流區塊鏈與中心化平臺TPS對比 區塊鏈與傳統計算的對比 區塊鏈可信且中立…

安全面試2

文章目錄 簡單描述一下什么是水平越權&#xff0c;什么是垂直越權&#xff0c;我要發現這兩類漏洞&#xff0c;那我代碼審計要注意什么地方水平越權&#xff1a;垂直越權&#xff1a;水平越權漏洞的審計重點垂直越權漏洞的審計重點 解釋一下ssrf漏洞原理攻擊場景修復方法 橫向移…

【Linux 專欄】echo命令實驗

風123456789&#xff5e;-CSDN博客 最近文章閱讀排行榜 【爬蟲基礎】第一部分 網絡通訊 P1/3-CSDN博客 【爬蟲基礎】第一部分 網絡通訊-Socket套接字 P2/3-CSDN博客 【Linux專欄】find命令同步 實驗-CSDN博客 【Linux運維】非root用戶的單向免密登錄_linux 單向免密-CSDN博客…

RTSP協議全解析

RTSP&#xff08;Real Time Streaming Protocol&#xff09;協議全解析 一、協議概述 定位&#xff1a;應用層協議&#xff0c;用于控制流媒體服務器&#xff08;播放、暫停、錄制&#xff09;&#xff0c;媒體傳輸由 RTP/RTCP 實現。 特點&#xff1a; 基于文本&#xff08;…

第15屆 藍橋杯 C++編程青少組中/高級選拔賽 202401 真題答案及解析

第 1 題 【 單選題 】 表達式117 % 16 的結果是( )。 A:0 B:5 C:7 D:10 解析: % 是取模運算符,用于計算兩個數相除后的余數。 計算 117 / 16,結果是 7,余數是 5。因此,117 % 16 = 5。答案: B 第 2 題 【 單選題 】 下列選項中,字符數組定義正確的是( …

qt5實現表盤的旋轉效果,通過提升QLabel類

因為工作需要&#xff0c;需要實現溫度的表盤展示效果 實現思路&#xff1a; 通過提示聲QLabel控價類&#xff0c;實現報盤的旋轉和展示效果 1. 編寫一個QLabel的類MyQLabel,實現兩個方法 1. void paintEvent(QPaintEvent *event); //重繪函數 2. void valueChanged(int va…

通信系統中物理層與網絡層聯系與區別

在通信系統中&#xff0c;物理層和網絡層是OSI&#xff08;開放系統互連&#xff09;模型中的兩個重要層次&#xff0c;分別位于協議棧的最底層和第三層。它們在功能、職責和實現方式上有顯著的區別&#xff0c;但同時也在某些方面存在聯系。以下是物理層與網絡層的聯系與區別的…

【深度學習】Pytorch的深入理解和研究

一、Pytorch核心理解 PyTorch 是一個靈活且強大的深度學習框架&#xff0c;廣泛應用于研究和工業領域。要深入理解和研究 PyTorch&#xff0c;需要從其核心概念、底層機制以及高級功能入手。以下是對 PyTorch 的深入理解與研究的詳細說明。 1. 概念 動態計算圖&#xff08;D…

23種設計模式 - 解釋器模式

模式定義 解釋器模式&#xff08;Interpreter Pattern&#xff09;是一種行為型設計模式&#xff0c;用于為特定語言&#xff08;如數控系統的G代碼&#xff09;定義文法規則&#xff0c;并構建解釋器來解析和執行該語言的語句。它通過將語法規則分解為多個類&#xff0c;實現…

使用 Openpyxl 操作 Excel 文件詳解

文章目錄 安裝安裝Python3安裝 openpyxl 基礎操作1. 引入2. 創建工作簿和工作表3. 寫入數據4. 保存工作簿5. 加載已存在的Excel6. 讀取單元格的值7. 選擇工作表 樣式和格式化1. 引入2. 設置字體3. 設置邊框4. 填充5. 設置數字格式6. 數據驗證7. 公式操作 性能優化1. read_only/…

nigix面試常見問題(2025)

一、Nginx基礎概念 1. 什么是Nginx? Nginx是一款高性能的HTTP/反向代理服務器及IMAP/POP3/SMTP代理服務器,由俄羅斯工程師Igor Sysoev開發。其核心優勢在于事件驅動架構與異步非阻塞處理模型,能夠高效處理高并發請求(如C10K問題),廣泛應用于負載均衡、靜態資源服務、AP…

002 SpringCloudAlibaba整合 - Feign遠程調用、Loadbalancer負載均衡

前文地址&#xff1a; 001 SpringCloudAlibaba整合 - Nacos注冊配置中心、Sentinel流控、Zipkin鏈路追蹤、Admin監控 文章目錄 8.Feign遠程調用、loadbalancer負載均衡整合1.OpenFeign整合1.引入依賴2.啟動類添加EnableFeignClients注解3.yml配置4.日志配置5.遠程調用測試6.服務…

代碼審計入門學習之sql注入

路由規則 入口文件&#xff1a;index.php <?php // ---------------------------------------------------------------------- // | wuzhicms [ 五指互聯網站內容管理系統 ] // | Copyright (c) 2014-2015 http://www.wuzhicms.com All rights reserved. // | Licensed …

React實現自定義圖表(線狀+柱狀)

要使用 React 繪制一個結合線狀圖和柱狀圖的圖表&#xff0c;你可以使用 react-chartjs-2 庫&#xff0c;它是基于 Chart.js 的 React 封裝。以下是一個示例代碼&#xff0c;展示如何實現這個需求&#xff1a; 1. 安裝依賴 首先&#xff0c;你需要安裝 react-chartjs-2 和 ch…

線程與進程的深入解析及 Linux 線程編程

在操作系統中&#xff0c;進程和線程是進行并發執行的兩種基本單位。理解它們的區別和各自的特點&#xff0c;能夠幫助開發者更好地進行多任務編程&#xff0c;提高程序的并發性能。本文將探討進程和線程的基礎概念&#xff0c;及其在 Linux 系統中的實現方式&#xff0c;并介紹…

全面指南:使用JMeter進行性能壓測與性能優化(中間件壓測、數據庫壓測、分布式集群壓測、調優)

目錄 一、性能測試的指標 1、并發量 2、響應時間 3、錯誤率 4、吞吐量 5、資源使用率 二、壓測全流程 三、其他注意點 1、并發和吞吐量的關系 2、并發和線程的關系 四、調優及分布式集群壓測&#xff08;待仔細學習&#xff09; 1.線程數量超過單機承載能力時的解決…

springboot整合mybatis-plus【詳細版】

目錄 一&#xff0c;簡介 1. 什么是mybatis-plus2.mybatis-plus特點 二&#xff0c;搭建基本環境 1. 導入基本依賴&#xff1a;2. 編寫配置文件3. 創建實體類4. 編寫controller層5. 編寫service接口6. 編寫service層7. 編寫mapper層 三&#xff0c;基本知識介紹 1. 基本注解 T…

HTTP 常見狀態碼技術解析(應用層)

引言 HTTP 狀態碼是服務器對客戶端請求的標準化響應標識&#xff0c;屬于應用層協議的核心機制。其采用三位數字編碼&#xff0c;首位數字定義狀態類別&#xff0c;后兩位細化具體場景。 狀態碼不僅是服務端行為的聲明&#xff0c;更是客戶端處理響應的關鍵依據。本文將從協議規…

Unity中的鍵位KeyCode

目錄 主要用途 檢測按鍵事件&#xff1a; 處理鍵盤輸入&#xff1a; 基本鍵位 常用鍵&#xff1a; 字母鍵&#xff1a; 數字鍵&#xff1a; 功能鍵&#xff1a; 方向鍵&#xff1a; 控制鍵&#xff1a; 鼠標鍵&#xff1a; 其他特殊鍵&#xff1a; 代碼示例 按下…