關于java的反射

???反射是啥呀相信許多學java的同學非常困惑在學的時候,總是感覺懂了卻又沒懂或者直接忽略過去了,那么本文就帶大家探討一下什么是反射在java中以及它的機制和運用。

??什么是反射:

首先我們知道一些知識:

維基百科的解釋

在計算機學中,反射式編程(英語:reflective programming)或反射(英語:reflection),是指計算機程序在運行時(runtime)可以訪問、檢測和修改它本身狀態或行為的一種能力.用比喻來說,反射就是程序在運行的時候能夠“觀察”并且修改自己的行為。
要注意術語“反射”和“內省”(type introspection)的關系。內省(或稱“自省”)機制僅指程序在運行時對自身信息(稱為元數據)的檢測;反射機制不僅包括要能在運行時對程序自身信息進行檢測,還要求程序能進一步根據這些信息改變程序狀態或結構。

這個解釋用在java就是通過jvm創建class示例進行操作反過來又能對對象進行訪問和修改。反射(Reflection)是 Java 的一種特性,它可以讓程序在運行時獲取自身的信息,并且動態地操作類或對象的屬性、方法和構造器等。通過反射功能,可以讓我們在不知道具體類名的情況下,依然能夠實例化對象,調用方法以及設置屬性。
首先知道一個加載過程
img
在這里插入圖片描述

Java語言的編譯過程主要包括以下幾個步驟:

詞法分析:
詞法分析器(Lexer)讀取源代碼文件,將源代碼中的字符序列轉換為記號(Token)序列。這些記號是編譯器進一步處理的基本單元。
語法分析:
語法分析器(Parser)根據Java語言的語法規則,將詞法分析器輸出的記號序列組織成語法樹(Abstract Syntax Tree, AST)。語法樹表示了源代碼中的程序結構。
語義分析:
語義分析器檢查語法樹是否滿足語義規則,比如變量是否已經聲明、類型是否匹配、表達式是否有意義等。這個階段還會進行一些類型推斷和轉換。
字節碼生成:
編譯器將經過語義分析后的語法樹轉換成字節碼(Bytecode)。字節碼是一種平臺無關的中間代碼,它可以在任何安裝了Java虛擬機(JVM)的平臺上運行。
具體來說,Java編譯過程如下:
源代碼到字節碼:
使用javac命令或Java編譯器API將.java源文件編譯成.class字節碼文件。這一步包含了上述的詞法分析、語法分析、語義分析和字節碼生成。
字節碼驗證:
當.class文件被加載到JVM時,字節碼驗證器會檢查字節碼文件,確保其遵循Java語言規范,沒有安全問題,比如確保不會發生數組越界、棧溢出等。
類加載:
類加載器(ClassLoader)負責將.class文件加載到JVM中,并為字節碼分配內存,將其轉換為運行時數據結構。
運行時優化:
JVM可能會對字節碼進行即時編譯(Just-In-Time, JIT)優化,將字節碼轉換成本地機器碼以提高執行效率。
執行:
最終,在JVM上執行這些字節碼,程序開始運行。
這個過程確保了Java語言的“一次編寫,到處運行”的特性,因為編譯生成的字節碼可以在任何有JVM的平臺上執行。

然后我們正式開始:
反射之中包含了一個「反」字,所以想要解釋反射就必須先從「正」開始解釋。

一般情況下,我們使用某個類時必定知道它是什么類,是用來做什么的。于是我們直接對這個類進行實例化,之后使用這個類對象進行操作。

Apple apple = new Apple(); //直接初始化,「正射」
apple.setPrice(4);

上面這樣子進行類對象的初始化,我們可以理解為「正」。

而反射則是一開始并不知道我要初始化的類對象是什么,自然也無法使用 new 關鍵字來創建對象了。

這時候,我們使用 JDK 提供的反射 API 進行反射調用:

Class clz = Class.forName("com.muggle.reflect.Apple");
Method method = clz.getMethod("setPrice", int.class);
Constructor constructor = clz.getConstructor();
Object object = constructor.newInstance();
method.invoke(object, 4);

上面兩段代碼的執行結果,其實是完全一樣的。但是其思路完全不一樣,第一段代碼在未運行時就已經確定了要運行的類(Apple),而第二段代碼則是在運行時通過字符串值才得知要運行的類(com.chenshuyi.reflect.Apple)。

所以說什么是反射?

反射就是在運行時才知道要操作的類是什么,并且可以在運行時獲取類的完整構造,并調用對應的方法。
(1)Java反射機制的核心是在程序運行時動態加載類并獲取類的詳細信息,從而操作類或對象的屬性和方法。本質是JVM得到class對象之后,再通過class對象進行反編譯,從而獲取對象的各種信息。

(2)Java屬于先編譯再運行的語言,程序中對象的類型在編譯期就確定下來了,而當程序在運行時可能需要動態加載某些類,這些類因為之前用不到,所以沒有被加載到JVM。通過反射,可以在運行時動態地創建對象并調用其屬性,不需要提前在編譯期知道運行的對象是誰。

??獲取Class對象的三種方式

package fanshe;
/*** 獲取Class對象的三種方式* 1 Object ——> getClass();* 2 任何數據類型(包括基本數據類型)都有一個“靜態”的class屬性* 3 通過Class類的靜態方法:forName(String  className)(常用)**/
public class Fanshe {public static void main(String[] args) {//第一種方式獲取Class對象  Student stu1 = new Student();//這一new 產生一個Student對象,一個Class對象。Class stuClass = stu1.getClass();//獲取Class對象System.out.println(stuClass.getName());//第二種方式獲取Class對象Class stuClass2 = Student.class;System.out.println(stuClass == stuClass2);//判斷第一種方式獲取的Class對象和第二種方式獲取的是否是同一個//第三種方式獲取Class對象try {Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必須是真實路徑,就是帶包名的類路徑,包名.類名System.out.println(stuClass3 == stuClass2);//判斷三種方式是否獲取的是同一個Class對象} catch (ClassNotFoundException e) {e.printStackTrace();}}
}

??反射的運用

框架:半成品軟件。可以在框架的基礎上進行軟件開發,簡化編碼
反射:將類的各個組成部分封裝為其他對象,這就是反射機制
? 好處:
? 可以在程序運行過程中,操作這些對象。
? 可以解耦,提高程序的可擴展性。
像咱們平時大部分時候都是在寫業務代碼,很少會接觸到直接使用反射機制的場景。但是,這并不代表反射沒有用。相反,正是因為反射,你才能這么輕松地使用各種框架。像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射機制。這些框架中也大量使用了動態代理,而動態代理的實現也依賴反射。比如下面是通過 JDK 實現動態代理的示例代碼,其中就使用了反射類 Method 來調用指定的方法。

public class DebugInvocationHandler implements InvocationHandler {/*** 代理類中的真實對象*/private final Object target;public DebugInvocationHandler(Object target) {this.target = target;}public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {System.out.println("before method " + method.getName());Object result = method.invoke(target, args);System.out.println("after method " + method.getName());return result;}
}

另外,像 Java 中的一大利器 注解 的實現也用到了反射。為什么你使用 Spring 的時候 ,一個@Component注解就聲明了一個類為 Spring Bean 呢?為什么你通過一個 @Value注解就讀取到配置文件中的值呢?究竟是怎么起作用的呢?這些都是因為你可以基于反射分析類,然后獲取到類/屬性/方法/方法的參數上的注解。你獲取到注解之后,就可以做進一步的處理。談談反射機制的優缺點優點:可以讓咱們的代碼更加靈活、為各種框架提供開箱即用的功能提供了便利缺點:讓我們在運行時有了分析操作類的能力,這同樣也增加了安全問題。比如可以無視泛型參數的安全檢查(泛型參數的安全檢查發生在編譯時)。
在使用 JDBC 連接數據庫時使用 Class.forName()通過反射加載數據庫的驅動程序,如果是mysql則傳入mysql的驅動類,而如果是oracle則傳入的參數就變成另一個了。

Spring 框架的 IOC(動態加載管理 Bean),Spring通過配置文件配置各種各樣的bean,你需要用到哪些bean就配哪些,spring容器就會根據你的需求去動態加載,你的程序就能健壯地運行。

還有Spring AOP(動態代理)功能都和反射有關系。

除此之外還有很多框架:mybatis、dubbo、rocketmq等等都會用到反射機制。


參考

反射的作用
大白話說反射
javaguide
java非常重要的基礎概念之一
反射

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

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

相關文章

武漢市集成電路領域重點產業鏈研究咨詢服務機構申報條件、時間

武漢市集成電路領域重點產業鏈研究咨詢服務機構公開遴選有關內容如下,武漢市的企業單位可以了解一下 一、采購內容 (一)項目名稱 武漢市集成電路領域重點產業鏈研究咨詢服務項目。 (二)項目內容 為進一步推動我市…

springboot項目 導入 maven坐標 錯誤 Could not transfer artifact XXX

1.報錯原因 當時導入的是 redis坐標 ,導入jar 包報錯(當時是網速太慢了,一直卡著不動 就關了 idea 重新下載)結果報錯 之前的redis 項目都可以的,網上找了一下 都沒解決 2.解決辦法 既然說不能傳輸, 就說…

有用的工具

一、appuploader Appuploader home -- A tool improve ios develop efficiency such as submit ipa to appstore and manage ios certificate這是一款p12證書查看的工具, 需要建立一個apple ID專用密碼:Manage your Apple ID

redis其他類型和配置文件

很多博客只講了五大基本類型,確實,是最常用的,而且百分之九十的程序員對于Redis只限于了解String這種最常用的。但是我個人認為,既然Redis官方提供了其他的數據類型,肯定是有相應的考量的,在某些特殊的業務…

C++相關概念和易錯語法(22)(final、純虛函數、繼承多態難點)

1.final final在繼承和多態中都可以使用,在繼承中是指不想將自己被繼承,在多態中是指不想該函數被重寫,比較簡單,下面是一些使用例子。 2.純虛函數 當我們需要抽象一個類的時候,我們就需要用到純虛函數。所謂抽象的類…

C# 4.0 等待線程結束

在C#中,如果你正在使用多線程編程,并且想要等待一個或多個線程完成它們的工作再繼續執行,有幾種方式可以實現。從C# 4.0開始,雖然直接用于等待線程結束的特性(如Thread.Join())在之前的版本中也已經存在&am…

升級版凱撒密碼加密解密器

目錄 開頭程序程序的流程圖程序加密與解密的效果例1加密的過程加密之后的文本 例2解密之后的文本解密之后的文本 例3加密之后的文本加密之后的文本 結尾 開頭 大家好,我叫這是我58。今天,我們來看一下我用C語言編譯的升級版凱撒密碼加密解密器和與之相關…

小程序 - - - - - 實現漸隱漸顯(監聽滾動距離版)

代碼如下&#xff1a; <!-- fixed-left --> <view class"fixed-box" animation"{{animationData}}">這里是漸隱漸顯的標簽 </view>.fixed-box {position: fixed;left: 0;top: 0;z-index: 999;background-color: #ccc;/* background-colo…

如何設計統計量及相關假設檢驗

一、如何設置H0和H1假設 誰做H0&#xff0c;誰做H1&#xff0c;在統計學的假設檢驗里是有約定俗成的規定的。即&#xff1a;status quo&#xff08;默認/現狀&#xff09;是H0&#xff0c;而新觀點或試圖challenge現狀的是H1。H1也叫research hypothesis&#xff0c;所以我們做…

【多個Python版本存在,使用pip+不同版本安裝庫時,windows彈出打開方式窗口的解決方法】

問題描述 電腦上存在python3.9&#xff0c;3.10&#xff0c;3.11&#xff0c;安裝順序也是先安裝3.9&#xff0c;然后3.10&#xff0c;最后3.11&#xff0c;那么直接使用pip安裝&#xff0c;會裝在3.11的位置&#xff0c;經過搜索可以通過pip版本&#xff0c;比如pip3.9 insta…

1.3- Zygote

第三節 Zygote 在Android系統中&#xff0c;Zygote是一個非常核心的組件&#xff0c;它扮演著孵化新應用程序進程的角色。Zygote是Android啟動過程中創建的第一個Java虛擬機&#xff08;JVM&#xff09;實例&#xff08;在Android中稱為Dalvik或ART虛擬機&#xff0c;取決于An…

如何在勒索軟件攻擊中幸存下來:最佳備份實踐、勒索攔截方案

無論身處什么業務或行業&#xff0c;數據都是您業務的關鍵資產。沒有針對數據進行安全可靠的備份保護&#xff0c;您將會受到許多“可能性”的威脅&#xff0c;無論數據丟失是由于在鍵盤上灑了飲料還是遭受到了勒索軟件的攻擊。 為了確保業務不被中斷&#xff0c;企業數據不會…

Python: 初識Python

文章目錄 1. Python的背景知識1.1 Python是咋來的?1.2 Python的特點1.3 Python能干啥?1.4 Python的缺點 2. 搭建Python環境2.1 安裝Python2.2 安裝PyCharm2.3 用pycharm編寫python程序 1. Python的背景知識 1.1 Python是咋來的? 由Guido van Rossum于1989年圣誕節為打發無…

一個用于管理多個 Node.js 版本的安裝和切換開源工具

大家好&#xff0c;今天給大家分享一個用于管理多個Node.js版本的工具 NVM&#xff08;Node Version Manager&#xff09;&#xff0c;它允許開發者在同一臺機器上安裝和使用不同版本的Node.js&#xff0c;解決了版本兼容性問題&#xff0c;為開發者提供了極大的便利。 在開發環…

路網雙線合并單線——ArcGISpro 解決方法

路網雙線合并成單線是一個在地圖制作、交通規劃以及GIS分析中常見的需求。雙線路網定義&#xff1a;具有不同流向、不同平面結構的道路。此外&#xff0c;車道數較多的道路&#xff08;例如&#xff0c;雙黃實線車道數大于4的道路&#xff09;也可以視為雙線路網&#xff0c;本…

iPhone 如何修改鎖屏密碼?修改密碼的具體步驟總結

修改 iPhone 鎖屏密碼 當你還記得當前設置的鎖屏密碼時&#xff0c;想要修改密碼就非常的簡單了&#xff0c;只需要簡單的點幾下就可以重新設置新密碼&#xff0c;下面是具體的操作步驟&#xff1a; 首先我們進入設置應用程序&#xff0c;然后找到“面容 ID 與密碼”。 然后需…

python3多進程用途和場景

Python3 的多進程模塊 multiprocessing 提供了多種用于并行處理的功能&#xff0c;適用于各種場景。以下是一些常見的用途和場景&#xff1a; 用途 CPU 密集型任務&#xff1a; 多進程適用于需要大量 CPU 計算的任務&#xff0c;例如數值計算、數據處理、圖像處理等。這些任務…

Redis的中BitMap的應用

一、應用場景 通常用于構建布隆過濾器 業務場景需要頻繁的查詢數據庫里的數據&#xff0c;但是這些數據又不一定都存在&#xff0c;一些大量無效的數據庫請求&#xff0c;占用了數據庫的鏈接。 本質上保護數據庫&#xff0c;減少無用的請求。 解決&#xff1a; 1、把查詢的…

(01)Unity使用在線AI大模型(使用百度千帆服務)

目錄 一、概要 二、環境說明 三、申請百度千帆Key 四、使用千帆大模型 四、給大模型套殼 一、概要 在Unity中使用在線大模型分為兩篇發布&#xff0c;此篇文檔為在Python中使用千帆大模型&#xff0c;整體實現邏輯是&#xff1a;在Python中接入大模型—>發布為可傳參的…

護眼臺燈的功能作用有哪些?深挖臺燈護眼是真的嗎

隨著現代生活方式的改變&#xff0c;孩子們面臨著越來越多的視力挑戰。在近視學生中&#xff0c;近10%為高度近視&#xff0c;且占比隨年級升高而增長。幼兒園6歲兒童中有1.5%為高度近視&#xff0c;而高中階段則達到了17.6%。為了守護孩子們的視力健康&#xff0c;在科技飛速發…