1 . 反射是在運作狀态中,對于任意一個類(class檔案),都能夠知道這個類的所有屬性和方法;對于任意一個對象,都隻能都調用它的任意一個方法和屬性,這種動态擷取的資訊一級動态調用對象的方法的功能呢個稱為java 的反射機制。
反射其實就是動态加載一個指定的類,并擷取該類中的所有的内容。而且将位元組碼檔案封裝成對象,并将位元組碼檔案中的内容都封裝成對象,這樣便于操作這些成員。就是把JAVA類中的各種成分反射成為相應的JAVA類簡單說:反射技術可以對一個類進行解剖
2. 反射的好處:大大的增強了程式的擴充性。
3. 反射的基本步驟:
(1)、獲得Class對象,就是擷取到指定的名稱的位元組碼檔案對象。
(2)、執行個體化對象,獲得類的屬性、方法或構造函數。
(3)、通路屬性、調用方法、調用構造函數建立對象。
4. 得到類的位元組碼檔案相同,這三種方式。
1. Class cls1=類名.class 相對簡單,還是需要明确類名
2. cls1.getclass();必須要明确具體的類,并建立對象
3. class.forName("完整的類名(帶包名)");
5. 九個預定義的Class執行個體對象:
(1). Integer.class包裝類的位元組碼
(2). Integer.TYPE Integer中基本類型的位元組碼
(3). int.class==Integer.TYPE
(4). 數組
A. class.isPrimitive();
B. class.isArray();
隻要在源程式中出現的類型,都有各自的Class執行個體對象,例如 int[] void 等等
(5). 建立類的對象
String name="com.dsa.類名";
(6). 尋找該名稱類檔案,并加載進記憶體,并非産生class對象:
Class clazz=Class.forName(name);
(7) . 産生該類的對象:
Object obj=clazz.newInstance();
(8). 得到某一個指定構造方法:
Constructor constructor= Class.forName("").getConstructor(String.class);
(9). 建立執行個體對象
Object obj=constructor.newInstance("abc");
6. 成員變量 Filed類 代表某個類中的一個成員變量
ReflectPoint pt1=new ReflectPoint(3,5);
Filed filedy=pt1.getclsss().getFiled("Y"); //隻代表哪個對象
Filed filedy=pt1.getclsss().getDeclaredField("x"); //擷取對象不管是私有還是被保護的
filedy.setAccessible(true); //設定可以通路,暴力反射
filedy.get(pt1); //取出Y的值
将字段中的b全變成a
Field[] fields=obj.getClass().getFields();//擷取全部對象
for(Field field :fields){
if(field.getType()==String.class){ //如果是字元串
String oldValue = (String)field.get(obj); //擷取字元串内容
String newValue = oldValue.replace('b','a'); //将字元串内容替換
field.set(obj,newValue); //将新值賦給對象
7. Method類成員方法的反射
擷取成員方法 反射形式:
Method methodCharAt = String.class.getMethod("charAt"--方法名,int.class--這是參數類型,如果是空參函數則是 null);
Object obj=clazz.newInstance(); methodCharAt.invoke(str1,1);
8. 數組的反射
Class clazz=obj.getClass();
if(clazz.isArray()){
int len=array.getLength(obj);
for(int i=0;i<len;I==){
sopArray.get(obj,i))
}
}
9. 反射來擷取泛型資訊
通過指定對應的Class對象,程式可以獲得該類裡面所有的Field,不管該Field使用private 方法public。獲得Field對象後都可以使用getType()來擷取其類型。
Class<?> type = f.getType(); //獲得字段的類型
但此方法隻對普通Field有效,若該Field有泛型修飾,則不能準确得到該Field的泛型參數,如Map<String,Integer>;為了獲得指定Field的泛型類型,我們采用:
Type gType = f.getGenericType();
得到泛型類型然後将Type對象強轉為ParameterizedType,其表示增加泛型後的類型
Type getRawType(); //傳回被泛型限制的類型
Type[] getActualTypeArguments(); //傳回泛型參數類型
10.利用反射來擷取泛型的類型(泛型資訊)
步驟:
(1). 擷取目前類
(2). 擷取目标字段
(3). 擷取包含泛型類型的類型 getGenericType()
(4). 強轉至子類ParameterizedType( 因為Type沒有任何對應的方法)
(5). 獲得泛型真正的類型 getActualTypeArguments()
11.例子:
package cn.itcast.day01;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
public class GetGenericTypeDemo{
Map<String,Integer> map = new HashMap<String,Integer>();
public static void main(String[] args) throws Exception {
Class c = GetGenericTypeDemo.class;
Field f = c.getDeclaredField("map");
System.out.println(f);
System.out.println(f.getName()); //map
// Class<?> getType() 傳回一個 Class 對象,它辨別了此 Field 對象所表示字段的聲明類型。
Class cl = f.getType();
System.out.println("獲得其類型:"+cl);//獲得其類型:interface java.util.Map
Type t = f.getGenericType();//包含泛型的類型
System.out.println(t); //java.util.Map<java.lang.String, java.lang.Integer
ParameterizedType pt = (ParameterizedType)t;//強轉到其子類
t = pt.getRawType();//類型的類或接口
System.out.println(t);
Type[] ts = pt.getActualTypeArguments();
for (Type type : ts) {
System.out.println(type);
}
}
}