java 反射機制_基礎篇:深入解析JAVA反射機制

88865cd1a956e36a1cf233252c79e9ab.gif

362414cdf445cefd39f997f8f3440672.png

反射的概念

  • java 的放射機制:在程序運行時,程序有能力獲取一個類的所有方法和屬性;并且對于任意一個對象,可以調用它的任意方法或者獲取其屬性

  • 通俗解析:java 文件需要編譯成. class 文件才能被 jvm 加載使用, 對象的. class 數據在 jvm 里就是 Class;我們如果能拿到這個 Class對象,就能獲取該 Class對應的對象類型,及在該類型聲明的方法和屬性值;還可以根據 Class創建相應的類型對象,通過 Field,Method 反過來操作對象

  • java 相關類介紹

類名描述
Class代表類的實體,在運行的 Java 應用程序中表示類或者接口
Field類的成員變量(成員變量也稱為類的屬性)
Method類的方法
Constructor類的構造方法

獲取 Class 的三種方法

  • 1 通過已知的類型獲取 class
//?根據Example?獲取Class?=》Example.class
public?Class?getExample(){
????Class?clazz?=?Example.class;return?clazz;
}
  • 2 通過實例對象獲取 class
public?Class?getExampleByInstance(){
????Example?example?=?new?Example();
????// getClass是Object類里面的方法;《?》?是通配符
????Class?clazz?=?example.getClass();return?(Class)clazz;
}
  • 3 通過 Class.forName 獲取全路徑指定類名的 class
/\*\*?forName0?本地方法,C++實現,jvm調用
?\* 1 className 是個類名? 2 initialize 是否延遲加載? 3 loader 加載器
?\*/
private?static?native?Class?forName0(String?className,?boolean?initialize,
????????ClassLoader?loader,?Class?caller)?throws?ClassNotFoundException;

public?static?Class?forName(String?className)?throws?ClassNotFoundException?{
????????Class?caller?=?Reflection.getCallerClass();
????????return?forName0(className,?true,?ClassLoader.getClassLoader(caller),?caller);
????}
//?兩個forName方法最終都會調用forName0方法去加載class???
public?static?Class?forName(String?name,
????????boolean?initialize,?ClassLoader?loader)?throws?ClassNotFoundException?{
????????....
????????return?forName0(name,?initialize,?loader,?caller);
????}
//?示例:通過java.lang.Integer?
public?Class?getInteger()throws?ClassNotFoundException{
????Class?clazz?=?Class.forName("java.lang.Integer");return?(Class)clazz;
}

JAVA 反射 API

  • Class 常用操作方法
//獲取所有的構造方法?/?private?public
public?Constructor\[\]?getDeclaredConstructors()
//獲取特定的構造方法?/?private?public
public?Constructor?getDeclaredConstructor(Class...?parameterTypes)????
//獲取類的父類
public?native?Class?getSuperclass()????
//獲取類實現的接口
private?Class\[\]?getInterfaces(boolean?cloneArray)??
//獲取在類內定義的內部類或接口
public?Class\[\]?getDeclaredClasses()
//獲取所有的方法
public?Method\[\]?getDeclaredMethods()?throws?SecurityException
//根據方法名和參數獲得特定的方法
public?Method?getDeclaredMethod(String?name,?Class...?parameterTypes)??
//獲取類型的定義的所有屬性
public?Field\[\]?getFields()?throws?SecurityException
//?根據屬性命名獲得特定的Field
public?Field?getField(String?name)?
  • Method 常用的操作方法
//獲得方法的放回類型
public?Class?getReturnType()???
//獲得方法的傳入參數類型
public?Class\[\]?getParameterTypes()???
//obj是實例對象,args是方法,反過來由Method控制對象的方法調用
public?Object?invoke(Object?obj,?Object...?args)
  • Field 常用的操作方法
//屬性與obj相等則返回true
public?boolean?equals(Object?obj)
//獲得obj中對應的屬性值
public?Object?get(Object?obj)
//設置obj中對應屬性值
public?void?set(Object?obj,?Object?value)?
  • Constructor
//根據傳遞的參數創建類的對象:initargs?構造方法參數
public?T?newInstance(Object...?initargs)?
  • 1 根據 class 創建對象
//方式一?clazz.newInstance()
Class?clazz?=?Example.class;
Example?example?=?clazz.newInstance();
//方式二?先獲取再由Constructor:clazz.getConstructors()/getConstructor(...)?
//再由Constructor.newInstance?方法構造對象
-----------------------------------------
public?class?Example?{
????private?int?value;
????public?Example(){?}?//?如果只聲明有參構造函數,clazz.newInstance()會報錯
????public?Example(Integer?value){??this.value??=?value;??}
????static?public?void?main(String\[\]?args)?throws?Exception{
????????Class?clazz?=?Example.class;
????????//根據指定構造函數參數獲取Constructor
????????Constructor?constructor?=?clazz.getConstructor(Integer.class);
????????Example?example?=?constructor.newInstance(100);
????????System.out.println(example.value);
????}
}????
  • 2 由 class 獲取 Field,并操作實例的屬性
public?class?Example?{
????private?int?value?,?count;
????static?public?void?main(String\[\]?args)?throws?Exception{
????????Class?clazz?=?Example.class;
????????//獲取所有的屬性,getField只能獲取public的屬性
????????Field\[\]?fs?=?clazz.getDeclaredFields();
????????//根據名稱獲取指定?Field
????????Field?value?=?clazz.getDeclaredField("value");
????????Example?example?=?clazz.newInstance();
????????//使用反射機制可以打破封裝性,導致了java對象的屬性不安全??
????????value.setAccessible(true);?//setAccessible(true)讓private的參數可賦值操作
????????//由Field反過去設置example的值
????????value.set(example,100);
????????System.out.println(example.value);
????}
}
  • 3 由 class 獲取 Method,并反射調用實例方法
public?class?Example?{
????public?static?void?main(String\[\]?args)?throws?Exception?{
????????Class?clazz?=?Example.class;
????????Example?example?=?clazz.newInstance();
????????Method\[\]?methods?=?clazz.getDeclaredMethods();
????????//getDeclaredMethod和getMethod是:getMethod只能返回public的方法
????????Method?method?=?clazz.getDeclaredMethod("hello",?String.class);
????????method.setAccessible(true);
????????method.invoke(example,?"cscw");
????}
????private?void?hello(String?name)?{?System.out.println(name?+?"?Hello!");?}
}
-----
cscw?Hello!

反射機制應用的場景

  • 1 動態拓展:假設有同一組類是實現相同的接口,并且類的加載方式不限制。當我們需要那種具體類實現的功能時,只需加載. class 文件,并獲取對應的 Class對象。可以由 Class 或者 Constructor 實例化對象 instance;根據接口定義,可以獲取 Class里的某一方法 Method,并配合 instance 反射調用功能方法

  • 2 Spring 的 IOC 就是基于反射機制實現

  • 3 JDK 的動態代理

反射和 JDK 動態代理

  • 在 Java 的 java.lang.reflect 包下提供了一個 Proxy 類和一個 InvocationHandler 接口。通過這個類和接口可以生成 JDK 動態代理類或動態代理對象
public?interface?InvocationHandler?{
?//所有方法都會調用此代理方法
????Object?invoke(Object?var1,?Method?var2,?Object\[\]?var3)?throws?Throwable;
}??
public?class?Proxy?implements?Serializable{
?...
????//根據interfaces和InvocationHandler生成代理對象
????public?static?Object?newProxyInstance(ClassLoader?loader,
??????Class\[\]?interfaces,?InvocationHandler?h)?
????...????

  • JDK 的動態代理由 Proxy 和 InvocationHandler 實現;而被代理對象必須實現一個接口。代理對象由 Proxy 生成,可轉為接口 interface 的實現類對象 OBJ。當調用 OBJ 的方法時,則會觸發 InvocationHandler.invoke,參數依次為「代理對象」「Method 對象」, 和「方法 Method 所需的參數」。在 invoke 方法可以加入拓展的邏輯,如日志記錄操作;「并可以在 invoke 里利用反射的技術調用被代理對象方法」

  • 示例

public?class?ExampleFactory?implements?InvocationHandler{
????private?T?target;?//被代理對象
????public?T?bind(T?obj){
????????target?=?obj;return?(T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),
???????????obj.getClass().getInterfaces(),this);
????}
????/\*\*?Object?o?是代理對象;?o的方法調用?->?ExampleFactory.invoke?
????\*??invoke(...)?->?在invoke方法里面?反射調用代理對象方法+增強邏輯
????\*/
????@Override
????public?Object?invoke(Object?o,?Method?method,?Object\[\]?objects)?throws?Throwable?{
????????//增強邏輯
????????System.out.println("log?start");
????????//反射調用被代理對象方法
????????Object?result?=?method.invoke(target,objects);
????????System.out.println("log?end");return?result;
????}
}
-----------
public?interface?Face?{
????void?hello(String?name);
}
---------
//被代理對象必須實現一個接口,并由接口方法對方提供功能
public?class?Example?implements?Face?{
?public?void?hello(String?name)?{
????????System.out.println(name?+?"?Hello!");
????}
????public?static?void?main(String\[\]?args)??{
???????//ExampleFactory?相當于一個中介人
????????ExampleFactory?factory?=?new?ExampleFactory<>();
????????//example?是代理對象
????????Face?example?=?exampleProxy.bind(new?Example());
????????example.hello("思婷");
????}
}
-----log?start
思婷?Hello!log?end

歡迎指正文中錯誤

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

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

相關文章

構建之法閱讀筆記01

本學期閱讀計劃有兩個&#xff0c;一個是《構建之法》&#xff0c;另一個是《大道至簡》。 在快速閱讀構建之法后&#xff0c;我想提一下幾個問題&#xff1a; 1、軟件程序軟件工程&#xff0c;那么只會軟件工程是怎樣具體詳細的將程序變成合格的軟件的&#xff1f; 2、效能分析…

html div float center,跨瀏覽器實現float:center

跨瀏覽器實現float:center互聯網 發布時間&#xff1a;2008-10-17 19:26:11 作者&#xff1a;佚名 我要評論原文&#xff1a;http://www.macji.com/blog/article/to-achieve-cross-browser-css-float-center/to-achieve-cross-browser-css-float-center/我們都知道float…

博弈論中:納什均衡、純策略納什均衡、混合策略納什均衡、占優策略

納什均衡 納什均衡是由約翰福布斯納什&#xff08;John Forbes Nash&#xff09;在20世紀50年代提出的博弈論概念&#xff0c;用于描述博弈中的一種穩定狀態。在納什均衡狀態下&#xff0c;每個參與者都假定其他參與者的策略是已知的&#xff0c;他們選擇的策略是最優的&#…

工具_HBuilder使用快捷方式

HBuilder常用快捷鍵大概共9類&#xff08;【4 13 3】文件、編輯、插入&#xff1b;【4 9 8】選擇、跳轉、查找&#xff1b;【1 1 6】運行、工具、視圖&#xff09; 1.文件(4) 新建 Ctrl N 關閉 Ctrl F4 全部關閉 Ctrl Shift F4 屬性 Alt Enter 2.編輯(13) 激活代碼助…

oracle左連接沒用_一周零基礎學完Oracle數據庫第三天02

四、 多表查詢1 什么是多表查詢多表查詢&#xff1a;當查詢的數據并不是來源一個表時&#xff0c;需要使用多表鏈接操作完成查詢。根據 不同表中的數據之間的關系查詢相關聯的數據。多表鏈接方式&#xff1a; 內連接&#xff1a;連接兩個表&#xff0c;通過相等或不等判斷鏈接列…

weblogic啟動項目報錯找不到類_啟動類報錯是經常出現的事但是單一的從一個地方找原因會越找越錯...

Error starting ApplicationContext. To display the conditions report rerun your application with debug enabled.當我們看到這個報錯的時候有的說是jar包重復&#xff0c;有的說是Controller包和Application包處于平行位置&#xff0c;還有的覺得是RequestMapping的valu…

fis

fis3實時刷新 npm install -g fis3 進入相關目錄 發布&#xff1a; fis3 release 啟動&#xff1a; fis3 server start // 服務啟動后&#xff0c;會一直存在&#xff0c;重啟或者fis3 server stop 才會關閉服務 自動刷新 fis3 release -wL關閉服務 fis3 server stop …

深入理解javascript原型和閉包(7)——原型的靈活性

在Java和C#中&#xff0c;你可以簡單的理解class是一個模子&#xff0c;對象就是被這個模子壓出來的一批一批月餅&#xff08;中秋節剛過完&#xff09;。壓個啥樣&#xff0c;就得是個啥樣&#xff0c;不能隨便動&#xff0c;動一動就壞了。 而在javascript中&#xff0c;就沒…

微型計算機一般不采用的控制方式,微型計算機控制作業.doc

作業一PID控制器引言在實際的過程控制與運動控制系統中&#xff0c;PID家族占據有相當的地位&#xff0c;據統計&#xff0c;工業控制的控制器中PID類控制占有90%以上。PID控制器是最早出現的控制器類型&#xff0c;因為其結構簡單&#xff0c;各個控制器參數有著明顯的物理意義…

js根據毫米/厘米算像素px

<html><meta http-equiv"content-type" content"text/html;charsetutf-8"><body> 紙張寬度(毫米mm)&#xff1a;<input type"text" id"width" value"10"> <span id"width_px"><…

c語言為什么有這么多的編程環境?_為什么98%的程序員學編程都會從C語言開始?...

在互聯網蓬勃發展的時代&#xff0c;有一類人做出了巨大的貢獻&#xff0c;這一群人被大家稱之為程序員&#xff0c;怎樣才能成為一名優秀的程序員呢&#xff0c;為什么每一個程序員都需要學習C語言呢&#xff1f;就讓我來跟大家分享分享&#xff1a;壹第一&#xff1a;相比較其…

怎么把電腦上的python軟件卸載干凈_怎么把一個軟件卸載干凈_把一個軟件卸載干凈的兩種方法-系統城...

平時使用電腦肯定有卸載軟件的操作&#xff0c;一般人直接用戶桌面的快捷方式刪除&#xff0c;表示軟件已經卸載干凈了&#xff0c;因為在桌面已經看不見了。其實大部分都沒有卸載干凈&#xff0c;如果沒卸載干凈&#xff0c;下載就無法安裝了&#xff0c;因為之前還有殘留文件…

2.x最終照著教程,成功使用OpenGL ES 繪制紋理貼圖,添加了灰度圖

在之前成功繪制變色的幾何圖形之后&#xff0c;今天利用Openg ES的可編程管線繪制出第一張紋理。學校時候不知道OpenGL的重要性&#xff0c;怕晦澀的語法。沒有跟老師學習OpenGL的環境配置&#xff0c;現在僅僅能利用cocos2dx 2.2.3 配置好的環境學習OpenGL ES。源碼來自《coco…

C# Dapper 簡單實例

/// <summary>/// 分頁信息/// </summary>public class PageInfo<T>{/// <summary>/// 分頁信息/// </summary>public PageInfo(){}/// <summary>/// 總頁數/// </summary>public long TotalCount{get; set;}/// <summary>///…

Angular 星級評分組件

一、需求演變及描述&#xff1a; 1. 有一個“客戶對公司的總體評價”的字段&#xff08;evalutation&#xff09;。字段為枚舉類型&#xff0c;0-5&#xff0c;對應關系為&#xff1a;0-暫無評價&#xff0c;1-很差&#xff0c;2-差&#xff0c;3-一般&#xff0c;4-好&#xf…

計算機網絡怎么查看連接打印機驅動,如何檢測網絡打印機是否已成功連接到計算機[檢測方法]...

大概很多嬰兒都像以前的編輯一樣. 使用網絡打印機時&#xff0c;有時它們可??以打印打印機沒有和電腦連接&#xff0c;有時卻不能. 那么如何檢測網絡打印機是否已成功連接到計算機&#xff1f;跟隨編輯器往下看.系統反復提示“無法打印”&#xff0c;因此本來很忙的小修幾乎快…

eclipse python插件_pydev插件下載-eclipse中的python插件下載6.0.0 官網最新版-西西軟件下載...

在eclipse中安裝python所需的插件。PyDev for Eclipse 是一個功能強大且易用的 Eclipse Python IDE 插件。利用 PyDev 插件把 Eclipse 變為功能強大且易用的 Python IDE&#xff0c;如何利用其進行 Python 程序的開發和調試。安裝方法&#xff1a;一種比較隨意的方法就是把壓縮…

a - 數據結構實驗之圖論一:基于鄰接矩陣的廣度優先搜索遍歷_數據結構--圖

故事凌 今天基本知識點圖可說是所有數據結構里面知識點最豐富的一個, 自己笨的知識點如下:階(oRDER), 度: 出度(out-Degree), 入度(in-Degree)樹(Tree), 森林(Forest), 環(Loop)有向圖(Directed Graph), 無向圖(Undirected Graph), 完全有向圖, 完全無向圖連通圖(Connected Gra…

vim: vimrc

2019獨角獸企業重金招聘Python工程師標準>>> 打造vim CIDE http://blog.csdn.net/doc_sgl/article/details/47205779 轉載于:https://my.oschina.net/u/2528742/blog/843176

計算機二級考試試題在線看,【TOP182015年全國計算機二級考試試題題庫.doc文檔免費在線閱讀材料】...

TOP182015年全國計算機二級考試試題題庫.doc文檔免費在線閱讀《2015年全國計算機二級考試試題題庫.doc》由會員分享&#xff0c;可免費在線閱讀全文&#xff0c;更多與《TOP182015年全國計算機二級考試試題題庫.doc文檔免費在線閱讀》相關文檔資源請在幫幫文庫(www.woc88.com)數…