Java反射機制是什么?

Java反射機制是 Java 語言的一個重要特性。

在學習 Java 反射機制前,大家應該先了解兩個概念,編譯期和運行期。

編譯期是指把源碼交給編譯器編譯成計算機可以執行的文件的過程。在 Java 中也就是把 Java 代碼編成 class 文件的過程。編譯期只是做了一些翻譯功能,并沒有把代碼放在內存中運行起來,而只是把代碼當成文本進行操作,比如檢查錯誤。

運行期是把編譯后的文件交給計算機執行,直到程序運行結束。所謂運行期就把在磁盤中的代碼放到內存中執行起來。

反射機制是什么?

Java反射機制是指在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法。

對于任意一個對象,都能夠調用它的任意一個方法和屬性,這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。

用一句話總結就是反射可以實現在運行時可以知道任意一個類的屬性和方法。

為什么要用反射?

Java 反射機制主要提供了以下功能,這些功能都位于java.lang.reflect包比如:

Java 反射機制主要包括以下幾個方面:

  • 獲取類的信息:反射機制允許程序在運行時獲取一個類的信息,例如:類的名稱、修飾符、父類、接口、屬性和方法等。
  • 創建對象:通過反射機制,程序可以在運行時創建一個類的實例對象,而不需要在編譯時知道這個類的類型。
  • 訪問屬性:通過反射機制,程序可以在運行時訪問一個對象的屬性,例如:獲取屬性值、設置屬性值、獲取屬性的類型和修飾符等。
  • 調用方法:通過反射機制,程序可以在運行時調用一個對象的方法,例如:獲取方法的參數、調用方法、獲取方法的返回值等。
  • 修改訪問權限:通過反射機制,程序可以在運行時修改對象的訪問權限,例如:設置屬性或方法的訪問權限為 public、private 或 protected。

Java 反射機制在實際應用中有廣泛的用途,例如:框架、動態代理、注解處理器等。反射機制雖然功能強大,但是也有一些缺點,例如:性能較低、安全性較差等,因此在使用時需要注意。

要想知道一個類的屬性和方法,必須先獲取到該類的字節碼文件對象。獲取類的信息時,使用的就是 Class 類中的方法。所以先要獲取到每一個字節碼文件(.class)對應的 Class 類型的對象。

眾所周知,所有 Java 類均繼承了 Object 類,在 Object 類中定義了一個 getClass() 方法,該方法返回同一個類型為 Class 的對象。

表列出了通過反射可以訪問的信息。

類型訪問方法返回值類型說明
包路徑getPackage()Package?對象獲取該類的存放路徑
類名稱getName()String 對象獲取該類的名稱
繼承類getSuperclass()Class 對象獲取該類繼承的類
實現接口getlnterfaces()Class 型數組獲取該類實現的所有接口
構造方法getConstructors()Constructor?型數組獲取所有權限為 public 的構造方法
getDeclaredContruectors()Constructor?對象獲取當前對象的所有構造方法
方法getMethods()Methods 型數組獲取所有權限為 public 的方法
getDeclaredMethods()Methods?對象獲取當前對象的所有方法
成員變量getFields()Field 型數組獲取所有權限為 public 的成員變量
getDeclareFileds()Field 對象獲取當前對象的所有成員變量
內部類getClasses()Class 型數組獲取所有權限為 public 的內部類
getDeclaredClasses()Class 型數組獲取所有內部類
內部類的聲明類getDeclaringClass()Class 對象如果該類為內部類,則返回它的成員類,否則返回 null

反射機制的優缺點

優點:

  • 能夠運行時動態獲取類的實例,大大提高系統的靈活性和擴展性。
  • 與 Java 動態編譯相結合,可以實現無比強大的功能。
  • 對于 Java 這種先編譯再運行的語言,能夠讓我們很方便的創建靈活的代碼,這些代碼可以在運行時裝配,無需在組件之間進行源代碼的鏈接,更加容易實現面向對象。

缺點:

  • 反射會消耗一定的系統資源,因此,如果不需要動態地創建一個對象,那么就不需要用反射;
  • 反射調用方法時可以忽略權限檢查,獲取這個類的私有方法和屬性,因此可能會破壞類的封裝性而導致安全問題。

?反射機制API

java.lang.Class 類

java.lang.Class 類是實現反射的關鍵所在,Class 類的一個實例表示 Java 的一種數據類型,包括類、接口、枚舉、注解(Annotation)、數組、基本數據類型和 void。Class 沒有公有的構造方法,Class 實例是由 JVM 在類加載時自動創建的。

在程序代碼中獲得 Class 實例可以通過如下代碼實現:

// 1. 通過類型class靜態變量
Class clz1 = String.class;
String str = "Hello";
// 2. 通過對象的getClass()方法
Class clz2 = str.getClass();

每一種類型包括類和接口等,都有一個 class 靜態變量可以獲得 Class 實例。另外,每一個對象都有 getClass() 方法可以獲得 Class 實例,該方法是由 Object 類提供的實例方法。

Class 類提供了很多方法可以獲得運行時對象的相關信息,下面的程序代碼展示了其中一些方法。

public class ReflectionTest01 {public static void main(String[] args) {// 獲得Class實例// 1.通過類型class靜態變量Class clz1 = String.class;String str = "Hello";// 2.通過對象的getClass()方法Class clz2 = str.getClass();// 獲得int類型Class實例Class clz3 = int.class;// 獲得Integer類型Class實例Class clz4 = Integer.class;System.out.println("clz2類名稱:" + clz2.getName());System.out.println("clz2是否為接口:" + clz2.isInterface());System.out.println("clz2是否為數組對象:" + clz2.isArray());System.out.println("clz2父類名稱:" + clz2.getSuperclass().getName());System.out.println("clz2是否為基本類型:" + clz2.isPrimitive());System.out.println("clz3是否為基本類型:" + clz3.isPrimitive());System.out.println("clz4是否為基本類型:" + clz4.isPrimitive());}
}

運行結果如下:

clz2類名稱:java.lang.String
clz2是否為接口:false
clz2是否為數組對象:false
clz2父類名稱:java.lang.Object
clz2是否為基本類型:false
clz3是否為基本類型:true
clz4是否為基本類型:false

java.lang.reflect 包

java.lang.reflect 包提供了反射中用到類,主要的類說明如下:

  • Constructor 類:提供類的構造方法信息。
  • Field 類:提供類或接口中成員變量信息。
  • Method 類:提供類或接口成員方法信息。
  • Array 類:提供了動態創建和訪問 Java 數組的方法。
  • Modifier 類:提供類和成員訪問修飾符信息。

示例代碼如下:

public class ReflectionTest02 {public static void main(String[] args) {try {// 動態加載xx類的運行時對象Class c = Class.forName("java.lang.String");// 獲取成員方法集合Method[] methods = c.getDeclaredMethods();// 遍歷成員方法集合for (Method method : methods) {// 打印權限修飾符,如public、protected、privateSystem.out.print(Modifier.toString(method.getModifiers()));// 打印返回值類型名稱System.out.print(" " + method.getReturnType().getName() + " ");// 打印方法名稱System.out.println(method.getName() + "();");}} catch (ClassNotFoundException e) {System.out.println("找不到指定類");}}
}

通過反射訪問構造方法

為了能夠動態獲取對象構造方法的信息,首先需要通過下列方法之一創建一個 Constructor 類型的對象或者數組。

  • getConstructors()
  • getConstructor(Class<?>…parameterTypes)
  • getDeclaredConstructors()
  • getDeclaredConstructor(Class<?>...parameterTypes)

如果是訪問指定的構造方法,需要根據該構造方法的入口參數的類型來訪問。例如,訪問一個入口參數類型依次為 int 和 String 類型的構造方法,下面的兩種方式均可以實現。

1、objectClass.getDeclaredConstructor(int.class,String.class);
2、objectClass.getDeclaredConstructor(new Class[]{int.class,String.class});

創建的每個 Constructor 對象表示一個構造方法,然后利用 Constructor 對象的方法操作構造方法。Constructor 類的常用方法如表所示。

表Constructor類的常用方法
方法名稱說明
isVarArgs()查看該構造方法是否允許帶可變數量的參數,如果允許,返回 true,否則返回
false
getParameterTypes()按照聲明順序以 Class 數組的形式獲取該構造方法各個參數的類型
getExceptionTypes()以 Class 數組的形式獲取該構造方法可能拋出的異常類型
newInstance(Object … initargs)通過該構造方法利用指定參數創建一個該類型的對象,如果未設置參數則表示
采用默認無參的構造方法
setAccessiable(boolean flag)如果該構造方法的權限為 private,默認為不允許通過反射利用?netlnstance()
方法創建對象。如果先執行該方法,并將入口參數設置為?true,則允許創建對
getModifiers()獲得可以解析出該構造方法所采用修飾符的整數

通過 java.lang.reflect.Modifier 類可以解析出 getMocMers() 方法的返回值所表示的修飾符信息。在該類中提供了一系列用來解析的靜態方法,既可以查看是否被指定的修飾符修飾,還可以字符串的形式獲得所有修飾符。表列出了 Modifier 類的常用靜態方法。

靜態方法名稱說明
isStatic(int mod)如果使用 static 修飾符修飾則返回 true,否則返回 false
isPublic(int mod)如果使用 public 修飾符修飾則返回 true,否則返回 false
isProtected(int mod)如果使用 protected 修飾符修飾則返回 true,否則返回 false
isPrivate(int mod)如果使用 private 修飾符修飾則返回 true,否則返回 false
isFinal(int mod)如果使用 final 修飾符修飾則返回 true,否則返回 false
toString(int mod)以字符串形式返回所有修飾符

例如,下列代碼判斷對象 con 所代表的構造方法是否被 public 修飾,以及以字符串形式獲取該構造方法的所有修飾符。

int modifiers = con.getModifiers(); // 獲取構造方法的修飾符整數
boolean isPublic = Modifier.isPublic(modifiers); // 判斷修飾符整數是否為public
string allModifiers = Modifier.toString(modifiers);

通過反射執行方法(獲取方法)

動態獲取一個對象方法的信息,首先需要通過下列方法之一創建一個 Method 類型的對象或者數組。

  • getMethods()
  • getMethods(String name,Class<?> …parameterTypes)
  • getDeclaredMethods()
  • getDeclaredMethods(String name,Class<?>...parameterTypes)

如果是訪問指定的構造方法,需要根據該方法的入口參數的類型來訪問。例如,訪問一個名稱為 max,入口參數類型依次為 int 和 String 類型的方法。

下面的兩種方式均可以實現:

1、objectClass.getDeclaredConstructor("max",int.class,String.class);
2、objectClass.getDeclaredConstructor("max",new Class[]{int.class,String.class});

Method 類的常用方法如表 3 所示。

靜態方法名稱說明
getName()獲取該方法的名稱
getParameterType()按照聲明順序以 Class 數組的形式返回該方法各個參數的類型
getReturnType()以 Class 對象的形式獲得該方法的返回值類型
getExceptionTypes()以 Class 數組的形式獲得該方法可能拋出的異常類型
invoke(Object obj,Object...args)利用 args 參數執行指定對象 obj 中的該方法,返回值為 Object 類型
isVarArgs()查看該方法是否允許帶有可變數量的參數,如果允許返回 true,否則返回 false
getModifiers()獲得可以解析出該方法所采用修飾符的整數

通過反射訪問成員變量?

通過下列任意一個方法訪問成員變量時將返回 Field 類型的對象或數組。

  • getFields()
  • getField(String name)
  • getDeclaredFields()
  • getDeclaredField(String name)

上述方法返回的 Field 對象代表一個成員變量。例如,要訪問一個名稱為 price 的成員變量,示例代碼如下:

object.getDeciaredField("price");

Field 類的常用方法如表所示

方法名稱說明
getName()獲得該成員變量的名稱
getType()獲取表示該成員變量的 Class 對象
get(Object obj)獲得指定對象 obj 中成員變量的值,返回值為 Object 類型
set(Object obj, Object value)將指定對象 obj 中成員變量的值設置為 value
getlnt(0bject obj)獲得指定對象 obj 中成員類型為 int 的成員變量的值
setlnt(0bject obj, int i)將指定對象 obj 中成員變量的值設置為 i
setFloat(Object obj, float f)將指定對象 obj 中成員變量的值設置為 f
getBoolean(Object obj)獲得指定對象 obj 中成員類型為 boolean 的成員變量的值
setBoolean(Object obj, boolean b)將指定對象 obj 中成員變量的值設置為 b
getFloat(Object obj)獲得指定對象 obj 中成員類型為 float 的成員變量的值
setAccessible(boolean flag)此方法可以設置是否忽略權限直接訪問 private 等私有權限的成員變量
getModifiers()獲得可以解析出該方法所采用修飾符的整數

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

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

相關文章

Python學習筆記第五十二天(Pandas 安裝)

Python學習筆記第五十二天 Pandas 安裝查看安裝版本 安裝驗證后記 Pandas 安裝 安裝 pandas 需要基礎環境是 Python&#xff0c;開始前我們假定你已經安裝了 Python 和 Pip。 使用 pip 安裝 pandas: pip install pandas安裝成功后&#xff0c;我們就可以導入 pandas 包使用&…

iPhone(iPad)安裝deb文件

最簡單的方法就是把deb相關的文件拖入手機對應的目錄&#xff0c;一般是DynamicLibraries文件夾 參考&#xff1a;探討手機越獄和安裝deb文件的幾種方式研究 1、在 Mac 上安裝 dpkg 命令 打包 deb 教程之在 Mac 上安裝 dpkg 命令_xcode打包root權限deb_qq_34810996的博客-CS…

神經網絡基礎-神經網絡補充概念-26-前向和反向傳播

簡單比較 前向傳播&#xff08;Forward Propagation&#xff09;&#xff1a; 前向傳播是神經網絡中的正向計算過程&#xff0c;用于從輸入數據開始&#xff0c;逐層計算每個神經元的輸出值&#xff0c;直到得到最終的預測值。在前向傳播過程中&#xff0c;我們按以下步驟進行…

驅動DAY4 字符設備驅動分步注冊和ioctl函數點亮LED燈

頭文件 #ifndef __HEAD_H__ #define __HEAD_H__ typedef struct{unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ODR; }gpio_t; #define PHY_LED1_ADDR 0X50006000 #define PHY_LED2_ADDR 0X50007000 #d…

一百五十八、Kettle——Kettle各版本及其相關安裝包分享(網盤鏈接,不需積分、不需驗證碼) 持續更新、持續分享

一、目的 最近因為kettle9.3的shim問題看了好多博客&#xff0c;都沒有網盤分享。后來有一位博主分享了kettle9.2的shim安裝包&#xff0c;已經很感謝他&#xff0c;但是是博客分享&#xff0c;下載還需要搞驗證碼下載碼之類的。 kettle9.2的shim安裝包下載好后&#xff0c;一…

圖數據庫_Neo4j基于docker服務版安裝_Neo4j Desktop桌面版安裝---Neo4j圖數據庫工作筆記0004

然后我們來看看如何用docker來安裝Neo4j community server 首先去執行docker pull neo4j:3.5.22-community 去拉取鏡像 然后執行命令就可以安裝了 可以用docker ps查看一下 看看暴露了哪些端口 然后再看一下訪問一下這個時候,要用IP地址了注意 然后再來看一下安裝Desktop 去下…

Sigmastar SSC8826Q 2K行車記錄儀解決方案

一、方案描述 行車記錄儀是智能輔助汽車駕駛&#xff0c;和管理行車生活的車聯網智能終端設備&#xff0c;利用智能芯片處理器、GPS定位、網絡通信、自動控制等技術&#xff0c;將與行車生活有關的各項數據有機地結合在一起。 行車記錄儀如今已經成了必不可少的車載用品之一&…

雙向-->帶頭-->循環鏈表

目錄 一、雙向帶頭循環鏈表概述 1.什么是雙向帶頭循環鏈表 2.雙向帶頭循環鏈表的優勢 3.雙向帶頭循環鏈表簡圖 二、雙向帶頭循環鏈表的增刪查改圖解及代碼實現 1.雙向帶頭循環鏈表的頭插 2.雙向帶頭循環鏈表的尾插 3.雙向帶頭循環鏈表的頭刪 4.雙向帶頭循環鏈表的尾刪…

ATF(TF-A) 威脅模型匯總

安全之安全(security)博客目錄導讀 目錄計劃如下&#xff0c;相關內容補充中&#xff0c;待完成后進行超鏈接&#xff0c;敬請期待&#xff0c;歡迎您的關注 1、通用威脅模型 2、SPMC威脅模型 3、EL3 SPMC威脅模型 4、fvp_r 平臺威脅模型 5、RSS-AP接口威脅模型 威脅建模是安全…

淺學實戰:探索PySpark實踐,解鎖大數據魔法!

文章目錄 Spark和PySpark概述1.1 Spark簡介1.2 PySpark簡介 二 基礎準備2.1 PySpark庫的安裝2.2 構建SparkContext對象2.3 SparkContext和SparkSession2.4 構建SparkSession對象2.5 PySpark的編程模型 三 數據輸入3.1 RDD對象3.2 Python數據容器轉RDD對象3.3 讀取文件轉RDD對象…

IDEA的常用設置,讓你更快速的編程

一、前言 在使用JetBrains的IntelliJ IDEA進行軟件開發時&#xff0c;了解和正確配置一些常用設置是非常重要的。IDEA的強大功能和定制性使得開發過程更加高效和舒適。 在本文中&#xff0c;我們將介紹一些常用的IDEA設置&#xff0c;幫助您更好地利用IDEA進行開發。這些設置包…

Java面向對象——封裝以及this關鍵字

封 裝 封裝是面向對象編程&#xff08;OOP&#xff09;的三大特性之一&#xff0c;它將數據和操作數據的方法組合在一個單元內部&#xff0c;并對外部隱藏其具體實現細節。在Java中&#xff0c;封裝是通過類的訪問控制修飾符&#xff08;如 private、protected、public&#x…

Linux MQTT智能家居項目(智能家居界面布局)

文章目錄 前言一、創建工程項目二、界面布局準備工作三、正式界面布局總結 前言 一、創建工程項目 1.選擇工程名稱和項目保存路徑 2.選擇QWidget 3.添加保存圖片的資源文件&#xff1a; 在工程目錄下添加Icon文件夾保存圖片&#xff1a; 將文件放入目錄中&#xff1a; …

網絡層協議

網絡層協議 IP協議基本概念協議頭格式網段劃分特殊的IP地址IP地址的數量限制私有IP地址和公網IP地址路由IP協議頭格式后續 在復雜的網絡環境中確定一個合適的路徑 IP協議 承接上文&#xff0c;TCP協議并不會直接將數據傳遞給對方&#xff0c;而是交付給下一層協議&#xff0c;…

機器學習基礎(四)

KNN算法 KNN:K-Nearest Neighbor,最近領規則分類。 為了判斷位置實例的類別,以所有已知類別的實例作為參照選擇參數K。計算未知實例與所有已知實例的距離。(一般采用歐氏距離)選擇最近K個已知實例。根據少數服從多數的投票法則,讓未知實例歸類為K個最近鄰樣本中最多數的類…

音視頻FAQ(三):音畫不同步

摘要 本文介紹了音畫不同步問題的五個因素&#xff1a;編碼和封裝階段、網絡傳輸階段、播放器中的處理階段、源內容產生的問題以及轉碼和編輯。針對這些因素&#xff0c;提出了相應的解決方案&#xff0c;如使用標準化工具、選擇強大的傳輸協議、自適應緩沖等。此外&#xff0…

uniapp微信小程序區分正式版,開發版,體驗版

小程序代碼區分是正式版&#xff0c;開發版&#xff0c;還是體驗版 通常正式和開發環境需要調用不同域名接口&#xff0c;發布時需要手動更換 或者有些東西不想在正式版顯示&#xff0c;只在開發版體驗版中顯示&#xff0c;也需要去手動隱藏 官方沒有明確給出判斷環境的方法&a…

SciencePub學術 | CCF推薦重點計算機SCIE征稿中

SciencePub學術 刊源推薦: CCF推薦重點計算機SCIE征稿中&#xff01;信息如下&#xff0c;錄滿為止&#xff1a; 一、期刊概況&#xff1a; CCF推薦重點SCIE簡介 【期刊簡介】IF&#xff1a;4.0&#xff0c;JCR2區&#xff0c;中科院3區&#xff1b; 【版面類型】正刊&#…

Swift 基礎

工程目錄 請點擊下面工程名稱&#xff0c;跳轉到代碼的倉庫頁面&#xff0c;將工程 下載下來 Demo Code 里有詳細的注釋 點擊下載代碼&#xff1a;swift-01

記錄一下基于jeecg-boot3.0的待辦消息移植記錄

因為之前沒有記錄&#xff0c;所以還要看代碼進行尋找&#xff0c;比較費勁&#xff0c;所以今天記錄一下&#xff1a; 1、后端 SysAnnouncementController 下面函數增加待辦的幾個顯示內容給前端用 具體代碼如下&#xff1a; /*** 功能&#xff1a;補充用戶數據&#xff0c…