黑馬程式設計師----Java基礎之反射
------- <a href="http://www.itheima.com" target="blank">android培訓</a>、<a href="http://www.itheima.com" target="blank">java培訓</a>、期待與您交流! ---------
反射:
反射的基石:::Class類
Java程式的各個Java類屬於同一類事物,描述這類事物的java類名就是Class;Class類代表Java類,它的各個例項物件分別對應各個類在記憶體中的位元組碼.
一個類被類載入器載入到記憶體中,佔用一片記憶體空間,這個空間裡面的內容就是類的位元組碼,不同的類的位元組碼是不同的,所以他們在記憶體中的內容志不同的,這一個個的空間可分別用一個個的物件來表示,這些物件顯然具有相同的型別
Java類用於描述一類事物的共性,該類事物有什麼屬性,沒有什麼什麼屬性,至於這個屬性的值是什麼,則是由這個類的例項物件來確定的,不同的Class,要注意與小寫class關鍵字的區別.Class類描述了那些方面的資訊?類的名字,類的訪問屬性,類所屬的包名,欄位名稱的列表等
得到各個位元組碼對應的例項物件的三種方式(Class 型別)
類名.class,例如:System.class
物件.getClass(),例如: new Date().getClass();
Class.forName("類名"),例如,Class.forName("java.util.Date");
物件名.isPrimitive();//判斷該物件是否是原始資料型別
舉例說明:
String str = "abc";
Class cl1 = str.getClass();
Class cl2 = String.class;
Class ci2 = Class.forName("java.lang.String");
cl1==cl2==cl3;
判斷是否為陣列的原始型別Class.isArray();
int.class==Integer.TYPE;
總之,只要是在源程式中出現的型別,都有各自的Class例項物件
反射:就是把Java類中的各種成分對映成相應的Java類,一個java類中用一個Class類的物件來表示,一個類中的組成部分:成員變數,方法,建構函式,包等等資訊也用一個個的java類來表示,就像汽車是一個類,汽車中的發動機,變速箱等等也是一個個的類.表示Java類的Class顯然要提供一系列的方法來獲得其中
一個類中的每個成員都可以用相應的反射API類的一個例項物件來表示,通過呼叫Class類的方法可以得到這些例項物件.
Constructor類
Constructor類代表某個類中的一個構造方法
得到某個類所有的構造方法:
例子:Constructor[] constructor = Class.forName("java.lang.String").getConstructors();
得到某一個構造方法:
例子:Constructor constructor = Class.forName("java.lang.String").getConstructors(StringBuilder.class);
建立例項物件:
通常方式;String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
用構造方法建立例項物件:
Constructor constructor1 = String.class.getConstructor(StringBuffer.class);
String str1 = (String)constructor1.newInstance(new StringBuffer("abc"));
char ch = str1.charAt(2);
System.out.println("ch="+ch);//結果為ch=c;
Class.newInstance()方法:直接建立空引數的構造方法(省略中間步驟,獲取構造方法類)
Field類:
Field類代表某個類中的一個成員變數
演示用eclips自動生成java類的構造方法
Method類
它代表某個類中的一個成員方法
得到類中某一個方法
例子:Method method= Class.forName("java.lang.String").getMethod("charAt",int.class)(方法名(字串),傳入的引數的位元組碼)
反射方式:System.out.println(method.invoke(Object obj , 1));
呼叫方法:
通常方式:System.out.println(str.charAt(1));
如果傳遞給Method物件的invoke方法的第一個引數為null,說明該Method物件對應的是一個靜態方法:
用反射方式執行某個類中的main方法;
目標:寫一個程式,這個程式那個根據使用者提供的類名,去執行該類中的main方法
陣列的反射
具有相同維數和元素型別的陣列屬於同一型別,即具有相同的Class例項物件.
代表陣列的Class例項物件getSuperClass()方法返回的父類的Object類對應的Class
基本型別的一維陣列可以被當作Object型別使用,不能當作Object[]型別使用;非基本型別的一維陣列,既可以當作Object[]型別使用,又可以當作Object型別使用.
Arrays.asList()方法處理int[]和String[]時的差異,Arrays工具類用於完成對陣列的反射操作
int[] a1= new int[3];
int[] a2 = new int[4];
int[][] a3 = new int[2][3];
String[] a4 = new String[3];
System.out,println(a1.getClass() == a2.getClass());//結果為true
System.out,println(a1.getClass() == a4.getClass());//結果為false
System.out,println(a1.getClass() == a3.getClass());//結果為false
System.out,println(a1.getClass().getSuperclass().getName());//結果為java.lang.Object
System.out,println(a4.getClass().getSuperclass().getName());//結果為java.lang.Object
基本資料型別的陣列不能轉換為Object的陣列
Object obj1 = a1;//結果為true
Object obj2 = a4;//結果為true
Object[] obj3 = a1;//結果為false
Object[] obj4 = a4;//結果為true
Object[] obj15= a3;//結果為true
用反射的思想列印基本資料型別的元素
public static void run(Object obj)
{
Class clazz = obj.getClass();
if(clazz.isArray())
{
int len = Array.getLength(obj);
for(int x=0; x<len; x++)
{
System.out.println(Array.get(obj), x);
}
}
else
System.out.println(obj);
}
反射的作用:實現框架功能
框架與框架要解決的核心問題
我做房子賣給使用者,由使用者自己安裝門窗和空調,我做的房子就是框架,使用者需要使用我的框架,把門窗插入進我提供的框架中,框架與工具類有區別,工具類被使用者的類呼叫,而框架則是呼叫使用者提供的類:
框架要解決的核心問題
我在寫框架的時候,,我怎樣保證我寫的框架程式怎樣能呼叫到你以後寫的類呢?
因為在寫程式是無法知道要被呼叫的類名,所以,在程式中無法直接new某個類的例項物件了,而要用到反射方式來做