一、什么叫反射?
首先給個定義:
? ? JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個實(shí)體類,都能夠知道這個類的所有屬性和方法验烧;對于任意一個對象,都能夠調(diào)用它的任意方法和屬性又跛;這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為java語言的反射機(jī)制碍拆。
?? 什么意思呢,簡單來說就是通過反射慨蓝,我們在程序運(yùn)行時可以獲得程序或者程序集中每一個類型的成員和成員信息感混。
?? java程序中的一般的對象的類型都是在編譯期就確定了下來,而java的反射機(jī)制可以動態(tài)地(在運(yùn)行期)創(chuàng)建對象并調(diào)用其屬性礼烈,這里創(chuàng)建的對象的類型在編譯期是未知的弧满。
反射的核心是JVM在運(yùn)行時才動態(tài)加載類或調(diào)用方法/訪問屬性,它不需要事先(寫代碼的時候或編譯期)知道運(yùn)行對象是誰此熬。
反射機(jī)制提供的功能:
1.在運(yùn)行時判斷任意一個對象所屬的類庭呜;
2.在運(yùn)行時構(gòu)造任意一個類的對象;
3.在運(yùn)行時判斷任意一個類所具有的成員變量和方法(通過反射甚至可以調(diào)用private方法)犀忱;
4.在運(yùn)行時調(diào)用任意一個對象的方法
二募谎、反射的用途
那么說了一堆,反射的到底能干什么呢峡碉?
在java EE 的世界里,反射機(jī)制最大的作用就是支持==以聲明式的方法(在XML中)來描述應(yīng)用的行為==驮审,是Struts,Spring ,Hibernate 核心技術(shù)之一鲫寄。
舉個栗子:
【Struts的例子:】在運(yùn)用Struts 2框架的開發(fā)中我們一般會在struts.xml里去配置Action吉执,比如:
- 在XML配置文件中定義Action
<action name="HelloWorld" class="example.HelloWorld">
<result>/hello.jsp</result>
</action
- 定義Java 類
public class HelloWorld extends ExampleSupport {
public String execute() throws Exception {
......
return SUCCESS;
}
.......
}
配置文件與Action建立了一種映射關(guān)系,當(dāng)View層發(fā)出請求時地来,請求會被StrutsPrepareAndExecuteFilter攔截戳玫,然后StrutsPrepareAndExecuteFilter會去動態(tài)地創(chuàng)建Action實(shí)例。
Struts 框架的作者事先肯定不知道你會配置一個HelloWorld的Action 未斑。
不過他可以這么做咕宿, Struts 在啟動以后,解析你配置XML配置文件蜡秽, 發(fā)現(xiàn)名稱為HelloWorld的Action, 找到相對于的類名example.HelloWorld, 然后就可以通過反射去實(shí)例化這個類府阀。 等到有人調(diào)用這個action 的時候, 可以通過反射來調(diào)用HelloWorld的execute() 方法芽突。
三试浙、反射基礎(chǔ):關(guān)于class類
1、Class是一個類寞蚌,一個描述類的類(也就是描述類本身)田巴,封裝了描述方法的Method,描述字段的Filed挟秤,描述構(gòu)造器的Constructor等屬性
2壹哺、對象照鏡子后(反射)可以得到的信息:某個類的數(shù)據(jù)成員名、方法和構(gòu)造器艘刚、某個類到底實(shí)現(xiàn)了哪些接口管宵。
3、對于每個類而言昔脯,JRE 都為其保留一個不變的 Class 類型的對象啄糙。一個Class對象包含了特定某個類的有關(guān)信息。
4云稚、Class 對象只能由系統(tǒng)建立對象
5隧饼、一個類在 JVM 中只會有一個Class實(shí)例
//總結(jié)一下就是,JDK有一個類叫做Class静陈,這個類用來封裝所有Java類型燕雁,包括這些類的所有信息,JVM中類信息是放在方法區(qū)的鲸拥。
//所有類在加載后拐格,JVM會為其在堆中創(chuàng)建一個Class<類名稱>的對象,并且每個類只會有一個Class對象刑赶,這個類的所有對象都要通過Class<類名稱>來進(jìn)行實(shí)例化捏浊。
//上面說的是JVM進(jìn)行實(shí)例化的原理,當(dāng)然實(shí)際上在Java寫代碼時只需要用 類名稱就可以進(jìn)行實(shí)例化了撞叨。
//總結(jié)一下就是金踪,JDK有一個類叫做Class浊洞,這個類用來封裝所有Java類型,包括這些類的所有信息胡岔,JVM中類信息是放在方法區(qū)的法希。
//所有類在加載后,JVM會為其在堆中創(chuàng)建一個Class<類名稱>的對象靶瘸,并且每個類只會有一個Class對象苫亦,這個類的所有對象都要通過Class<類名稱>來進(jìn)行實(shí)例化。
//上面說的是JVM進(jìn)行實(shí)例化的原理怨咪,當(dāng)然實(shí)際上在Java寫代碼時只需要用 類名稱就可以進(jìn)行實(shí)例化了屋剑。
public final class Class<T> implements java.io.Serializable,
GenericDeclaration,
Type,
AnnotatedElement {
虛擬機(jī)會保持唯一一
//通過類名.class獲得唯一的Class對象。
Class<UserBean> cls = UserBean.class;
//通過integer.TYPEl來獲取Class對象
Class<Integer> inti = Integer.TYPE;
//接口本質(zhì)也是一個類惊暴,一樣可以通過.class獲取
Class<User> userClass = User.class;
四饼丘、反射的基本運(yùn)用
一、使用反射機(jī)制創(chuàng)建實(shí)例辽话,并調(diào)用其方法
示例類:
package com.example;
public class HelloWorld {
public HelloWorld(){
}
public void sayHello(){
System.out.println("hello world!");
}
}
//第一步肄鸽, 先把HelloWorld的類裝載進(jìn)來
Class cls = Class.forName("com.example.HelloWorld");
//第二步, 創(chuàng)建一個HelloWorld的實(shí)例油啤, 注意典徘, 這里并沒有用強(qiáng)制轉(zhuǎn)型把obj轉(zhuǎn)成HelloWorld
Object obj = cls.newInstance();
//第三步, 得到這個類的方法益咬, 注意逮诲, 一個類的方法也是對象啊
Method m = cls.getDeclaredMethod("sayHello");
//第四步, 方法調(diào)用幽告, 輸出"hello world"
m.invoke(obj);
二梅鹦、更多基本應(yīng)用:參考這里
1.判斷是否為某個類的實(shí)例
2.獲取某個class對象的方法集合
3.為某個class對象創(chuàng)建實(shí)例
4.獲取構(gòu)造器的信息
5.調(diào)用方法
6.獲取class類的成員變量
文章主要參考:(謝謝!H咚F胨簟!6澈印)