首先有兩個問題:
1> 什麼是Java的反射機制?
2> 反射機制有什麼作用?
<1> 反射機制指的是我們可以於運行時加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個運行時才得知名稱的class,獲悉其完整構造(但不包括methods定義),並生成其對象實體、或對其fields設值、或喚起其methods。
<2>反射能夠讓我們:
在運行時檢測對象的類型;動態構造某個類的對象;檢測類的屬性和方法,並調用;任意調用對象的方法;修改構造函數、方法、屬性的可見性;
用處:
對於Web框架,開發人員在配置文件中定義他們對各種接口和類的實現。通過反射機制,
例如,Spring框架使用如下的配置文件:
<bean id="someID" class="com.programcreek.Foo">
<property name="someField" value="someValue" />
</bean>
當Spring容器處理元素時,會使用Class.forName(“com.programcreek.Foo”)來初始化這個類,並再次使用反射獲取元素對應的setter方法,爲對象的屬性賦值。
Servlet也會使用相同的機制:
<servlet>
<servlet-name>someServlet</servlet-name>
<servlet-class>com.programcreek.WhyReflectionServlet</servlet-class>
<servlet>
介紹三個對象的機制與實現:
類對象(Class類的某一個具體類對象)
實例化對象(某一具體類的實例對象)
a. Class對象的機制與實現(假設已經存在普通類Book)
Class就是類的類型。Integer,String...這些類的類型就是Class
1 三種*類對象*的獲取方式
Class cl1 (類的類型) = Class.forName("一個類的完整路徑名")
2 類的實例化對象來獲取類對象
Object ob = new Book();
Class cl2 (類的類型) = ob.getClass();
3 直接使用類.class
Class cl3 = Book.class;
通過類對象可以實例化一個對象
Book bk = (Book)cl1.newInstance(); //默認返回一個Object類的對象,實例化類對象,無參,無參。
b. Field對象的機制與實現
Java.lang.reflect.Field類,用於表示類中,接口中屬性對象的類。
可以操作類中私有,以及公有等全部屬性和屬性的信息。
package com.java.test;
import com.java.bean.Book;
import java.lang.reflect.Field;
public class TestField {
//使用傳遞過來的Class對象獲取類中的屬性
public void show(Class cls){
//數組中每一個Field對象都是Book的一個屬性
Field[] fid = cls.getDeclaredFields(); //可以將私有屬性獲取到
//Field[] fid = cls.getFields(); //只能獲取到公有屬性
for (Field f : fid){
System.out.println(f.getName());
System.out.println(f.getType());
}
}
//該方法使用傳遞過來的實體類對象獲取屬性
public void show2(Object obj){
Class cls = obj.getClass(); //獲取類對象,感覺還是回到了第一種方式
Field[] fid = cls.getDeclaredFields();
for (Field fi : fid){
try {
fi.setAccessible(true); //可以理解爲啓用私有屬性的訪問權限
System.out.println(fi.getName()+"值: "+fi.get(obj));//get是將屬性值取出來
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
Book bk = new Book();
bk.setId(1);
bk.setName("JVM虛擬機");
bk.setType("Java");
TestField tf = new TestField();
//tf.show(Book.class);
tf.show2(bk);
}
}
c. Method對象的機制與實現
Java.lang.reflect.Method類是用於表示類中,接口中方法對象的類。
可以操作類中私有,以及公有…全部方法。
package com.java.test;
import com.java.bean.Book;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class TestMethod {
//該方法用於獲取對象的所有方法名稱 返回值類型 以及參數信息
public void show(Object obj){
Class cls = obj.getClass();
Method[] me = cls.getDeclaredMethods(); //獲取到Book類中所有的方法
for (Method m : me){
System.out.println("Name: "+m.getName()); //方法名
System.out.println("Type: "+ Modifier.toString(m.getModifiers())); //方法修飾符
System.out.println("Return: "+m.getReturnType()); //方法返回值
Class[] praType = m.getParameterTypes(); //獲取方法參數
System.out.println("params: ");
for (Class c : praType){
System.out.println(c.getName());
}
}
try {
Method mt = cls.getMethod("getName",null); //獲取到方法後進行調用
try {
//此處如果有多個參數的話,先把參數保存在數組(數組可以爲Object類型)裏。
mt.invoke(obj,new Object[0]); //obj對象調用getName()方法,參數爲null(有點反射的意思了呦)
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Book bk = new Book();
bk.setId(1);
bk.setName("JVM虛擬機");
bk.setType("Java");
TestMethod tm = new TestMethod();
tm.show(bk);
}
}