黑馬程式設計師Java培訓和Android培訓Java技術二

iteye_5923發表於2011-07-02
黑馬程式設計師
二十一
位元組碼用等號比。
作業:將任意一個物件中的所有String型別的成員變數所對應的字串內容中的"b"改為"a"。
關鍵程式碼:
private static void changeStringValue(Object obj ) throws Exception
{
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');
//System.out.println("zzz");
field.set(obj, newValue);
}
}

}

二十二
Method類
Method類代表某個類中的一個成員方法
得到類中的某一個方法:
例子:Method charAt=Class.forName("java.lang.String").getMethod("charAt",int.class);
呼叫方法:
通常方式:System.out.println(str.charAt(1));
反射方法:System.out.println(charAt.invoke(str,1));
如果傳遞給Method物件invoke()方法的第一個引數為null,這有著什麼樣的意義呢?說明該Method物件對應的是一個靜態方法!
jdk1.4和jdk1.5的invoke方法的區別:
Jdk1.5:public Object invoke(Object obj,Object...args)
Jdk1.4:public Object invoke(Object obj,Object[] args),即按jdk1.4的語法,需要將一個陣列作為引數傳遞給invoke方法時,陣列中的每個元素分別對應被指定的型別。

二十三
用反射方式執行某個類中的main方法(按下F2出現完整的類名)
目標:
寫一個程式,這個程式能夠根據使用者提供的類名,去執行該類中的mai方法。用普通方式呼叫後即類名.main(new String[]{"xxx"})的方式。
問題:
啟動Java程式的main方法的引數是一個字串陣列,即public static void main(String[] args),通過反射方式來呼叫這個main方法時,如何為invoke方法傳遞引數呢?按jdk1.5的語法,整個陣列是一個引數,而按jdk1.4的語法,陣列中的每個元素對應一個引數,當把一個字串陣列作為引數傳遞給invoke方法時,javac會到底按哪種語法進行處理呢?jdk1.5肯定要相容jdk1.4的語法,會按1.4的語法進行處理,即把陣列打散成為若干個單獨的引數。所以,在給main方法傳遞引數時,不能使用程式碼mainMethod.invoke(null,new String[]{"xxx"}),javac只把它當作jdk1.4的語法進行理解,而不把它當作jdk1.5的語法解釋,因此會出現引數型別不對的問題。
解決辦法:
mainMethod.invoke(null,new Object[]{new String[]{"xxx"}});
mainMethod.invoke(null,(Object)new String[]{"xxx"});,編譯器會作特殊處理,編譯時不把引數當作陣列看待,也就不會把陣列打散成若干個引數了。或者將引數強制轉換成為Object物件。

二十四
陣列的反射
具有相同維數和元素型別的陣列屬於同一個型別,即具有相同的Class例項物件。
代表陣列的Class例項物件的getSuperClass()方法返回的父類的Object類對應的Class。
基本型別的一維陣列可以被當作Object型別使用,不能當作Object[]型別使用,非基本型別的一維陣列,既可以被當作Object型別使用,也可以當作Object[]型別使用。
Arrays.aList()方法處理int[]和String[]時的差異。不能列印出int[],只能列印出String[]。

二十五
Array工具類用於完成對陣列的反射操作。
思考題:怎麼得到陣列中的元素型別?沒有辦法得到。但是可以將每個元素單獨拿出來來得到該陣列的型別。

二十六
ArrayList與hashSet
ArrayList是一種有順序的集合,有位置順序。而HashSet是在將物件放入它裡面時,先比較裡面是否有那個物件,如果有則不再重複放入;如果非要放入,則要先將存在的物件刪除掉,再放入。

二十七
反射的作用--->實現框架功能
框架與框架要解決的核心問題
我做房子賣給使用者住,由使用者自己安裝門窗和空調,我做的房子就是框架,使用者需要使用我的框架,把門窗插入進我提供的框架中。框架與工具類有區別,工具類被使用者的類呼叫,而框架則是呼叫使用者提供的類。

框架要解決的核心問題
我在寫框架( 房子)時,你這個使用者可能還在上小學,還不會寫程式呢?我寫的框架程式怎樣能呼叫到你以後寫的類(門窗)呢?
因為在寫才程式時無法知道要被呼叫的類名,所以,在程式中無法直接new某個類的例項物件了,而要用反射方式來做。

綜合案例
先直接用new語句建立ArrayList和HashSet例項物件,演示用eclipse自動生成ReflectPoint類的equals和hashcode方法,比較兩個集合的執行結果差異。
然後改為採用配置檔案加反射的方式建立ArrayList和HashSet的例項物件,比較觀察執行結果差異。引入了eclipse對資原始檔的管理方式的講解。

二十八
用類載入器的方式管理資源和配置檔案
配置檔案的路徑要使用絕對路徑。使用getRealPath()方法來得到絕對路徑。一定要記住用完整的路徑,但完整的路徑不是硬編碼,而是運算出來的。

類載入器:類名.class.getClassLoader().getResourceAsStream(name)name要寫出配置檔案的路徑和配置檔名稱。或者使用 類名.class.getResourceAsStream(name)name直接使用配置檔名稱。
以後學到的框架使用者配置檔案都是放在ClassPath中的。

二十九
IntroSpector-->操作JavaBean-->JavaBean是一個特殊的Java類
例如:
class Person
{
private int x;
public int getAge()
{
return x;
}
public void setAge(int age)
{ this.x=age}
}
以上的Person類有一個JavaBean式的屬性是age;命名規則如果第二個字母是小寫的,則把第一個字母變成小的。

例如:
gettime-->time
setTime-->time
getCPU--> CPU


內省-->瞭解JavaBean
JavaBean是一種特殊的Java類,主要用於傳遞資料資訊,這種java類中的方法主要用於訪問私有的欄位,且方法名符合某種命名規則。
如果要在兩個模組直接傳遞多個資訊,可以將這些資訊封裝到一個JavaBean中,這種JavaBean的例項物件通常稱之為值物件,則需要通過一些相應的方法來訪問,大家覺得這些方法的名稱叫什麼好呢?JavaBean的屬性是根據其中的setter和getter方法來確定的,而不是根據其中的成員變數。如果方法名為setId,中文意思即為設定id,至於你從哪個變數上取,用管嗎?去掉set字首,剩餘部分就是屬性名,如果剩餘部分的第二個字母是小寫的,則把剩餘部分的首字母改成小寫的。(如上例子所說,部分原因是為了識別方便)。總之,一個類被當作javaBean使用時,JavaBean的屬性是根據方法名推斷出來的,它根本看不到java類內部的成員變數。

一個符合JavaBean特點的類可以當作普通類一樣進行使用,但把它當作JavaBean用肯定需要帶來一些額外的好處,我們才會去了解和應用JavaBean!好處如下:
1在JavaEE開發中,經常要使用到JavaBean。很多環境就要求按JavaBean方式進行操作,別人都這麼用和要求這麼做,那你就沒什麼挑選的餘地!
2JDK中提供了對JavaBean進行操作的一些API,這套API就稱為內省。如果要你自己去通過getX方法來訪問私有的x,那怎麼做?用內省這套api操作JavaBean比用普通類的方式更方便。


三十
內省綜合案例(可以利用滑鼠右鍵Refactor來抽取某幾行程式碼組成的方法)
演示用eclipse自動生成ReflectPoint類的setter和getter方法。
直接new一個PropertyDescription物件的方式來讓大家瞭解JavaBean API的價值,先用一段程式碼讀取JavaBean的屬性,然後再用一段程式碼設定JavaBean的屬性。
演示用eclipse將讀取屬性和設定屬性的流水帳程式碼分別抽取成方法:
---呼叫這個方法,並給這個方法傳遞了一個物件,屬性名和設定值,它就能完成屬性修改的功能。
---得到BeanInfo最好採用"obj.getClass()",而不要採用"類名.class"方式,這樣程式更通用。
採用遍歷BeanInfo的所有屬性方式來查詢和設定某個RefectPoint物件的屬性。在程式中把一個類當作JavaBean來看,就是呼叫IntroSpector.getBeanInfo方法,得到的Beaninfo物件封裝了把這個類當作JavaBean看的結果訊息。

相關文章