java反射簡單例子
今天又被學員問到這個問題了,索性專門做個小知識點來講解反射是怎麼起作用的,發現還是可以在不學習Spring等框架的基礎上,舉一些例子來輔助理解反射如何起作用。
鑑於手機知乎上看程式碼格式會亂掉,所以程式碼都截圖
1. 首先準備兩個很簡單的業務類
<img src="https://pic2.zhimg.com/50/v2-aacd60547555dd41116a3288ca549785_hd.png" data-rawwidth="495" data-rawheight="206" class="origin_image zh-lightbox-thumb" width="495" data-original="https://pic2.zhimg.com/v2-aacd60547555dd41116a3288ca549785_r.png"><img src="https://pic1.zhimg.com/50/v2-4410be8aedf7a91db4350ca4e9b89e6c_hd.png" data-rawwidth="496" data-rawheight="202" class="origin_image zh-lightbox-thumb" width="496" data-original="https://pic1.zhimg.com/v2-4410be8aedf7a91db4350ca4e9b89e6c_r.png">
2. 非反射方式切換不同的業務方法呼叫
<img src="https://pic2.zhimg.com/50/v2-6d07614e59386775c738db0e573ca9a5_hd.png" data-rawwidth="538" data-rawheight="207" class="origin_image zh-lightbox-thumb" width="538" data-original="https://pic2.zhimg.com/v2-6d07614e59386775c738db0e573ca9a5_r.png">當需要從第一個業務方法切換到第二個業務方法的時候,使用非反射方式,必須修改程式碼,並且重新編譯執行,才可以達到效果
3. 反射方式
使用反射方式,首先準備一個配置檔案,就叫做spring.txt吧, 放在src目錄下。 裡面存放的是類的名稱,和要呼叫的方法名。
在測試類Test中,首先取出類名稱和方法名,然後通過反射去呼叫這個方法。
當需要從呼叫第一個業務方法,切換到呼叫第二個業務方法的時候,不需要修改一行程式碼,也不需要重新編譯,只需要修改配置檔案spring.txt,再執行即可。
<img src="https://pic2.zhimg.com/50/v2-77ffdf1131e3cf1cfea3c48aac79f951_hd.png" data-rawwidth="346" data-rawheight="144" class="content_image" width="346"><img src="https://pic3.zhimg.com/50/v2-80cd1a6134c5e5c051807ddb949e9282_hd.png" data-rawwidth="884" data-rawheight="678" class="origin_image zh-lightbox-thumb" width="884" data-original="https://pic3.zhimg.com/v2-80cd1a6134c5e5c051807ddb949e9282_r.png">
使用這個例子,可以較好得理解反射的一個應用場景。
這也是Spring框架的最基本的原理,只是它做的更豐富,安全,健壯。
這個例子如果有興趣自己照著做一遍,我放在這裡:
二、反射的主要用途
很多人都認為反射在實際的Java開發應用中並不廣泛,其實不然。
當我們在使用IDE(如Eclipse,IDEA)時,當我們輸入一個物件或類並想呼叫它的屬性或方法時,一按點號,編譯器就會自動列出它的屬性或方法,這裡就會用到反射。
反射最重要的用途就是開發各種通用框架。
很多框架(比如Spring)都是配置化的(比如通過XML檔案配置JavaBean,Action之類的),為了保證框架的通用性,它們可能需要根據配置檔案載入不同的物件或類,呼叫不同的方法,這個時候就必須用到反射——執行時動態載入需要載入的物件。
舉一個例子,在運用Struts 2框架的開發中我們一般會在struts.xml裡去配置Action,比如:
123456 | <action name="login" class="org.ScZyhSoft.test.action.SimpleLoginAction" method="execute"> <result>/shop/shop-index.jsp</result> <result name="error">login.jsp</result> </action> |
配置檔案與Action建立了一種對映關係,當View層發出請求時,請求會被StrutsPrepareAndExecuteFilter攔截,然後StrutsPrepareAndExecuteFilter會去動態地建立Action例項。
——比如我們請求login.action,那麼StrutsPrepareAndExecuteFilter就會去解析struts.xml檔案,檢索action中name為login的Action,並根據class屬性建立SimpleLoginAction例項,並用invoke方法來呼叫execute方法,這個過程離不開反射。
對與框架開發人員來說,反射雖小但作用非常大,它是各種容器實現的核心。而對於一般的開發者來說,不深入框架開發則用反射用的就會少一點,不過了解一下框架的底層機制有助於豐富自己的程式設計思想,也是很有益的。
四、反射的一些注意事項(待補充)
由於反射會額外消耗一定的系統資源,因此如果不需要動態地建立一個物件,那麼就不需要用反射。
另外,反射呼叫方法時可以忽略許可權檢查,因此可能會破壞封裝性而導致安全問題