




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Java基礎(chǔ)加強(qiáng)王昭珽JDK5.0新特性JDK5中新增了很多新的java特性,利用這些新語法可以幫助開發(fā)人員編寫出更加高效、清晰,安全的代碼。靜態(tài)導(dǎo)入自動(dòng)裝箱/拆箱增強(qiáng)for循環(huán)可變參數(shù)枚舉反射注解泛型靜態(tài)導(dǎo)入JDK1.5增加的靜態(tài)導(dǎo)入語法用于導(dǎo)入類的某個(gè)靜態(tài)屬性或方法。使用靜態(tài)導(dǎo)入可以簡(jiǎn)化程序?qū)︻愳o態(tài)屬性和方法的調(diào)用。它完全是為了便利而增加的新特性語法:Importstatic
包名.類名.靜態(tài)屬性|靜態(tài)方法|*例如:importstaticjava.lang.System.out//靜態(tài)導(dǎo)入類成員importstaticjava.lang.Math.*//使用通配符靜態(tài)導(dǎo)入—小細(xì)節(jié)importstaticjava.util.Arrays.sort;importstaticjava.util.Collections.sort;這是允許的,運(yùn)行時(shí)會(huì)根據(jù)參數(shù)來自動(dòng)找到對(duì)應(yīng)的方法。注:如果導(dǎo)入的兩個(gè)靜態(tài)方法的參數(shù)也是一樣的話,由于不能確定是哪個(gè)方法,所有使用時(shí)需要小心自動(dòng)裝箱/拆箱Java中的基本類型不是對(duì)象,因此包裝類用來當(dāng)做對(duì)象版本的基本類型。當(dāng)你要在兩者之間來來回回轉(zhuǎn)換時(shí),事情就變得很討厭了。如下所示:春天來了,Tiger中提供了兩個(gè)新的功能----裝箱和拆箱,來自動(dòng)執(zhí)行這些轉(zhuǎn)換。自動(dòng)裝箱/拆箱自動(dòng)裝箱:指開發(fā)人員可以把一個(gè)基本數(shù)據(jù)類型直接賦值給對(duì)應(yīng)的包裝類。Autoboxing自動(dòng)拆箱:指開發(fā)人員可以把一個(gè)包裝類對(duì)象直接賦給對(duì)應(yīng)的基本數(shù)據(jù)類型。Autounboxing典型應(yīng)用:
自動(dòng)裝箱/拆箱思考:Integeri=null;intj=i;語法有無錯(cuò)誤,能否運(yùn)行?自動(dòng)裝箱/拆箱—細(xì)節(jié)1Java的規(guī)范指出:特定的基本類型一定得被box成相同的包裝類型。這些對(duì)象會(huì)被高速緩存以重復(fù)使用,并且會(huì)被當(dāng)做一般對(duì)象使用。這些特殊的值是boolean值的true和false、所有的byte值、介于-128至127的short與int值,以及介于\u0000與\u007F之間的任何一個(gè)char。自動(dòng)裝箱/拆箱—細(xì)節(jié)2在一般的情況下,Java借由使用方法的名稱來調(diào)用method。在方法有重載的情況下,需要檢查方法的參數(shù)來決定調(diào)用哪個(gè)方法,如果沒有找到符合的參數(shù),會(huì)出現(xiàn)編譯錯(cuò)誤。增強(qiáng)for循環(huán)增強(qiáng)for循環(huán)又稱為“foreach”或“enhancedfor”循環(huán)拋棄迭代:在JDK5以前的版本中,遍歷數(shù)組或集合中的元素,需先獲得數(shù)組的長(zhǎng)度或集合的迭代器,比較麻煩!因此JDK5中定義了一種新的語法——增強(qiáng)for循環(huán),以簡(jiǎn)化此類操作。增強(qiáng)for循環(huán)只能用在數(shù)組、或?qū)崿F(xiàn)Iterable接口的子類上語法格式: for(變量類型變量:需迭代的數(shù)組或集合) }示例:操作數(shù)組、List和Map(傳統(tǒng)&Foreache)增強(qiáng)for循環(huán)使用增強(qiáng)for循環(huán)的幾個(gè)注意事項(xiàng)(以下程序的輸出結(jié)果?)intarr[]=newint[5];for(intnum:arr){ num=1;}System.out.println(arr[0]);List<String>list=newArrayList<String>();list.add("xxx");for(Stringstr:list){ str="yyy";}System.out.println(list.get(0));可變參數(shù)思考假如你要寫幾個(gè)方法,分別用于計(jì)算2個(gè)整數(shù)之和、3個(gè)整數(shù)之和、4個(gè)整數(shù)之和………..你該怎么做?可變參數(shù)可變參數(shù)(variableargument)允許你指定可以采用多個(gè)同類型參數(shù)的方法,而不需要事先確定參數(shù)的數(shù)目??勺儏?shù)。語法:
publicvoidfoo(int…args){ }注意事項(xiàng):調(diào)用可變參數(shù)的方法時(shí),編譯器將自動(dòng)創(chuàng)建一個(gè)數(shù)組保存?zhèn)鬟f給方法的可變參數(shù),因此,程序員可以在方法體中以數(shù)組的形式訪問可變參數(shù)在一個(gè)方法參數(shù)中只能使用一個(gè)省略號(hào);且省略號(hào)必須出現(xiàn)在方法中參數(shù)列表的最后一個(gè)位置。不可變類不可變類,是指當(dāng)創(chuàng)建了這個(gè)類的實(shí)例后,就不允許修改它的屬性值。在JDK的基本類庫(kù)中,所有基本類型的包裝類,如Integer和Long及String,都是不可變類。如果創(chuàng)建了他們的對(duì)象,在程序代碼中無法再改變這些對(duì)象的值,因?yàn)樗麄儧]有提供修改屬性的方法。不可變類能是程序更加安全,不容易出錯(cuò)不可變類是線程安全的,當(dāng)多個(gè)線程訪問不可變類的同一個(gè)實(shí)例時(shí),無需進(jìn)行線程同步。用戶自定義不可變類1、把屬性privatefinal類型2、不對(duì)外公開修改屬性的set方法,只提供get方法3、在構(gòu)造方法中初始化所有屬性4、覆蓋Object類的equals和hashCode方法在創(chuàng)建不可變類時(shí),假如它的屬性的類型是可變類型,在必要的情況下,必須提供保護(hù)性拷貝,否則,這個(gè)不可變類實(shí)例的屬性仍然有可能被錯(cuò)誤地修改。看以下代碼:不可變類---改進(jìn)通過采用保護(hù)性拷貝,其他程序無法獲得與Schedule對(duì)象關(guān)聯(lián)的Date對(duì)象的引用如果Schedule類中被final修飾的屬性所屬的類是不可變類,就無需提供保護(hù)性拷貝,因?yàn)樵搶傩运玫膶?shí)例值永遠(yuǎn)不會(huì)被改變枚舉類為什么需要枚舉?一些方法在運(yùn)行時(shí),它需要的數(shù)據(jù)不能是任意的,而必須是一定范圍內(nèi)的值,比如成績(jī)Grade只能為ABCDE。此類問題在JDK5以前采用自定義帶有枚舉功能的類解決,Java5以后可以直接使用枚舉予以解決。JDK5新增的enum關(guān)鍵字用于定義一個(gè)枚舉類。一個(gè)枚舉也可以有構(gòu)造函數(shù)、字段和方法示例枚舉類帶抽象方法的枚舉枚舉類枚舉類具有如下特性:枚舉類也是一種特殊形式的Java類。枚舉類中聲明的每一個(gè)枚舉值代表枚舉類的一個(gè)實(shí)例對(duì)象。與java中的普通類一樣,在聲明枚舉類時(shí),也可以聲明屬性、方法和構(gòu)造函數(shù),但枚舉類的構(gòu)造函數(shù)必須為私有的(這點(diǎn)不難理解)。枚舉類也可以實(shí)現(xiàn)接口、或繼承抽象類。JDK5中擴(kuò)展了swith語句,它除了可以接收int,byte,char,short外,還可以接收一個(gè)枚舉類型。若枚舉類只有一個(gè)枚舉值,則可以當(dāng)作單態(tài)設(shè)計(jì)模式使用。枚舉類Java中聲明的枚舉類,均是java.lang.Enum類的孩子,它繼承了Enum類的所有方法。常用方法:name()ordinal()valueof(Stringname)此方法雖然在JDK文檔中查找不到values()此方法雖然在JDK文檔中查找不到,但每個(gè)枚舉類都具有該方法,它遍歷枚舉類的所有枚舉值非常方便。練習(xí):請(qǐng)編寫一個(gè)關(guān)于星期幾的枚舉WeekDay,要求:枚舉值:Mon,Tue,Wed,Thu,Fri,Sat,Sun該枚舉要有一個(gè)方法,調(diào)用該方法返回中文格式的星期。創(chuàng)建對(duì)象思考如何創(chuàng)建一個(gè)對(duì)象,有幾種方式?反射什么是反射?反射就是把Java類中的各種成分映射成一個(gè)個(gè)的java對(duì)象。例如,一個(gè)類有:成員變量,方法,構(gòu)造方法,包等等信息,利用反射技術(shù)可以對(duì)一個(gè)類進(jìn)行解剖,把各個(gè)組成部分映射成一個(gè)個(gè)對(duì)象。反射用在哪里?QuickStart:利用反射加載一個(gè)類并調(diào)用其中的方法Class類要利用反射,必須先得到代表字節(jié)碼的Class。Class類用于表示.class文件(字節(jié)碼)。如何得到某個(gè)class文件對(duì)應(yīng)的class對(duì)象。類名.class,對(duì)象.getClass()Class.forName(“類名”)
基本類型的包裝類.TYPE總之,只要是在源程序中出現(xiàn)的類型,都有各自的Class實(shí)例對(duì)象,例如,int,void…解剖類Class對(duì)象提供了如下常用方法:publicConstructorgetConstructor(Class<?>…parameterTypes)publicMethodgetMethod(Stringname,Class<?>…parameterTypes)publicFieldgetField(Stringname)publicpublicConstructorgetDeclaredConstructor(Class<?>…parameterTypes)publicMethodgetDeclaredMethod(Stringname,Class<?>…parameterTypes)publicFieldgetDeclaredField(Stringname)這些方法分別用于從類中解剖出構(gòu)造函數(shù)、方法和成員變量(屬性)。解剖出的成員分別使用Constructor、Method、Field對(duì)象表示。思考:假設(shè)你是一個(gè)框架的設(shè)計(jì)者,解剖出這些成員后干什么?利用Constructor創(chuàng)建對(duì)象Constructor類提供了如下方法,用于創(chuàng)建類的對(duì)象:publicObjectnewInstance(Object…initargs)initargs用于指定構(gòu)造函數(shù)接收的參數(shù)練習(xí):反射類無參、有參、私有的構(gòu)造函數(shù),創(chuàng)建類的對(duì)象Class類的newInstance()方法也可創(chuàng)建類的實(shí)例,其內(nèi)部工作原理是先得無參的構(gòu)造方法,再用構(gòu)造方法創(chuàng)建實(shí)例對(duì)象。Stringobj=(String)Class.forName("java.lang.String").newInstance();利用Method調(diào)用方法Method提供了如下方法,用于執(zhí)行它所代表的方法publicObjectinvoke(Objectobj,Object…args)練習(xí):使用Method分別執(zhí)行無參、有參、多參(帶數(shù)組和基本數(shù)據(jù)類型)、靜態(tài)、私有的方法反射main方法jdk1.4和jdk1.5的invoke方法的區(qū)別1.5:publicObjectinvoke(Objectobj,Object…args)1.4:publicObjectinvoke(Objectobj,Object[]args)反射main方法問題:?jiǎn)?dòng)Java程序的main方法的參數(shù)是一個(gè)字符串?dāng)?shù)組,即publicstaticvoidmain(String[]args),通過反射方式來調(diào)用這個(gè)main方法時(shí),如何為invoke方法傳遞參數(shù)呢?按jdk1.5的語法,整個(gè)數(shù)組是一個(gè)參數(shù),而按jdk1.4的語法,數(shù)組中的每個(gè)元素對(duì)應(yīng)一個(gè)參數(shù),當(dāng)把一個(gè)字符串?dāng)?shù)組作為參數(shù)傳遞給invoke方法時(shí),javac會(huì)到底按照哪種語法進(jìn)行處理呢?jdk1.5肯定要兼容jdk1.4的語法,會(huì)按jdk1.4的語法進(jìn)行處理,即把數(shù)組打散成為若干個(gè)單獨(dú)的參數(shù)。所以,在給main方法傳遞參數(shù)時(shí),不能使用代碼mainMethod.invoke(null,newString[]{“xxx”}),javac只把它當(dāng)作jdk1.4的語法進(jìn)行理解,而不把它當(dāng)作jdk1.5的語法解釋,因此會(huì)出現(xiàn)參數(shù)類型不對(duì)的問題。解決辦法:mainMethod.invoke(null,newObject[]{newString[]{"xxx"}});mainMethod.invoke(null,(Object)newString[]{"xxx"});,編譯器會(huì)作特殊處理,編譯時(shí)不把參數(shù)當(dāng)作數(shù)組看待,也就不會(huì)數(shù)組打散成若干個(gè)參數(shù)了Field類Field類代表某個(gè)類中的一個(gè)成員變量練習(xí):私有變量、靜態(tài)變量、公共變量實(shí)例編寫一個(gè)基于xml的配置文件<?xmlversion="1.0"encoding="UTF-8"?><beans><beanid="demo"class="cn.itcast.Student"method="sleep"/></beans>利用反射手法動(dòng)態(tài)加載類并執(zhí)行方法內(nèi)省(Introspector)—JavaBean為什么要學(xué)內(nèi)???開發(fā)框架時(shí),經(jīng)常需要使用java對(duì)象的屬性來封裝程序的數(shù)據(jù),每次都使用反射技術(shù)完成此類操作過于麻煩,所以SUN公司開發(fā)了一套API,專門用于操作java對(duì)象的屬性。什么是JavaBean和屬性的讀寫方法?通過內(nèi)省技術(shù)訪問(java.beans包提供了內(nèi)省的API)JavaBean的兩種方式。通過PropertyDescriptor類操作Bean的屬性通過Introspector類獲得Bean對(duì)象的BeanInfo,然后通過BeanInfo來獲取屬性的描述器(PropertyDescriptor),通過這個(gè)屬性描述器就可以獲取某個(gè)屬性對(duì)應(yīng)的getter/setter方法,然后通過反射機(jī)制來調(diào)用這些方法。北京傳智播客教育PropertyDescriptor來操作屬性:PropertyDescriptor顧名思義,就是屬性描述之意。它通過反射快速操作JavaBean的getter/setter方法。重要方法:getWriteMethod()–獲取setter方法,返回Method對(duì)像
getReadMethod()–獲取getter方法,返回Method對(duì)像內(nèi)省(Introspector)--練習(xí)北京傳智播客教育內(nèi)省—beanutils工具包:Beanutils是Apache開發(fā)的一套快速操作JavaBeangetter/setter方法的API,目前比較流行。準(zhǔn)備包:mons-logging.jar語法:設(shè)置:BeanUtils.setProperty(Objectbean,StringpropertyName,StringpropertyValue);獲取:BeanUtils.getProperty(Objectbean,StringPropetyName);BeanUtils示例設(shè)置屬性值類型的自動(dòng)轉(zhuǎn)換類型轉(zhuǎn)換器北京傳智播客教育BeanUtils將Map屬性自動(dòng)放到Bean中可以操作成功的原則-Map的key必須要與Bean的屬性一致。Mapm=newHashMap();m.put("name","roseJack");Personperson=newPerson();BeanUtils.populate(person,m);System.err.println(person);北京傳智播客教育使用BeanUtils實(shí)現(xiàn)級(jí)聯(lián)操作:泛型(Generic)—泛形的作用JDK5以前,對(duì)象保存到集合中就會(huì)失去其特性,取出時(shí)通常要程序員手工進(jìn)行類型的強(qiáng)制轉(zhuǎn)換,這樣不可避免就會(huì)引發(fā)程序的一些安全性問題。例如:ArrayListlist=newArrayList();list.add("abc");Integernum=(Integer)list.get(0);//運(yùn)行時(shí)會(huì)出錯(cuò),但編碼時(shí)發(fā)現(xiàn)不了list.add(newRandom());list.add(newArrayList());for(inti=0;i<list.size();i++){ (?)list.get(i);//此處取出來的對(duì)象應(yīng)轉(zhuǎn)換成什么類型}泛型(Generic)—泛形的作用JDK5中的泛形允許程序員在編寫集合代碼時(shí),就限制集合的處理類型,從而把原來程序運(yùn)行時(shí)可能發(fā)生問題,轉(zhuǎn)變?yōu)榫幾g時(shí)的問題,以此提高程序的可讀性和穩(wěn)定性(尤其在大型程序中更為突出)。注意:泛型是提供給javac編譯器使用的,它用于限定集合的輸入類型,讓編譯器在源代碼級(jí)別上,即擋住向集合中插入非法數(shù)據(jù)。但編譯器編譯完帶有泛形的java程序后,生成的class文件中將不再帶有泛型信息,以此使程序運(yùn)行效率不受到影響,這個(gè)過程稱之為“擦除”。泛形的基本術(shù)語,以ArrayList<E>為例:<>念著typeofArrayList<E>中的E稱為類型參數(shù)變量ArrayList<Integer>中的Integer稱為實(shí)際類型參數(shù)整個(gè)稱為ArrayList<E>泛型類型整個(gè)ArrayList<Integer>稱為參數(shù)化的類型ParameterizedType泛型典型應(yīng)用使用迭代器迭代泛形集合中的元素。使用增強(qiáng)for循環(huán)迭代泛形集合中的元素。存取HashMap中的元素。使用泛形時(shí)的幾個(gè)常見問題:使用泛形時(shí),泛形類型須為引用類型,不能是基本數(shù)據(jù)類型ArrayList<String>list=newArrayList<Object>();ArrayList<Object>list=newArrayList<String>();ArrayList<String>list=newArrayList();ArrayListlist=newArrayList<String>();自定義泛形——泛型方法Java程序中的普通方法、構(gòu)造方法和靜態(tài)方法中都可以使用泛型。方法使用泛形前,必須對(duì)泛形進(jìn)行聲明,語法:<T>,T可以是任意字母,但通常必須要大寫。<T>通常需放在方法的返回值聲明之前。例如:
publicstatic<T>voiddoxx(Tt);練習(xí):編寫一個(gè)泛形方法,實(shí)現(xiàn)數(shù)組元素的交換。編寫一個(gè)泛形方法,接收一個(gè)任意數(shù)組,并顛倒數(shù)組中的所有元素。注意:只有引用類型才能作為泛型方法的實(shí)際參數(shù)。北京傳智播客教育在類上面定義的范型:public
classA<T>{ publicTgetT(Class<T>cls)throwsException{ Tt=cls.newInstance(); returnt; }}類上面定義的泛型不適用與靜態(tài)方法自定義泛形——泛型類和反射泛形如果一個(gè)類多處都要用到同一個(gè)泛型,這時(shí)可以把泛形定義在類上(即類級(jí)別的泛型),語法格式如下:
publicclassGenericDao<T>{ privateTfield1; publicvoidsave(Tobj){} publicTgetId(intid){} }注意,靜態(tài)方法不能使用類定義的泛形,而應(yīng)單獨(dú)定義泛形。泛形的典型應(yīng)用:BaseDao和反射泛型泛型的高級(jí)應(yīng)用——通配符定義一個(gè)方法,接收一個(gè)集合,并打印出集合中的所有元素,如下所示:
voidprint(Collection<String>c){
for(Stringe:c){
System.out.println(e);
}}
問題:該方法只能打印保存了Object對(duì)象的集合,不能打印其它集合。通配符用于解決此類問題,方法的定義可改寫為如下形式:voidprint(Collection<?>c){
//Collection<?>(發(fā)音為:"collectionofunknown")
for(Objecte:c){ System.out.println(e);}}此種形式下需要注意的是:由于print方法c參數(shù)的類型為Collection<?>,即表示一種不確定的類型,因此在方法體內(nèi)不能調(diào)用與類型相關(guān)的方法,例如add()方法??偨Y(jié):使用?通配符主要用于引用對(duì)象,使用了?通配符,就只能調(diào)對(duì)象與類型無關(guān)的方法,不能調(diào)用對(duì)象與類型有關(guān)的方法。泛型的高級(jí)應(yīng)用——有限制的通配符限定通配符的上邊界:正確:Vector<?extendsNumber>x=newVector<Integer>();錯(cuò)誤:Vector<?extendsNumber>x=newVector<String>();限定通配符的下邊界:正確:Vector<?superInteger>x=newVector<Number>();錯(cuò)誤:Vector<?superInteger>x=newVector<Byte>();publicvoidadd(List<?extendsString>list){ list.add("abc");}問題:以下代碼行不行?Annotation(注解)概述注解起到標(biāo)識(shí)做用。比如Junit的@Test注解。Junit會(huì)在運(yùn)行時(shí)檢查方法上是否存在此注解,如果存在,就通過反射來運(yùn)行你的方法從JDK5.0開始,Java增加了對(duì)元數(shù)據(jù)(MetaData)的支持,也就是Annotation(注解)。三個(gè)基本的Annotation:@Override:限定重寫父類方法,該注解只能用于方法@Deprecated:用于表示某個(gè)程序元素(類,方法等)已過時(shí)@SuppressWarnings:抑制編譯器警告.Annotation其實(shí)就是代碼里的特殊標(biāo)記,它用于替代配置文件,也就是說,傳統(tǒng)方式通過配置文件告訴類如何運(yùn)行,有了注解技術(shù)后,開發(fā)人員可以通過注解告訴類如何運(yùn)行。在Java技術(shù)里注解的典型應(yīng)用是:可以通過反射技術(shù)去得到類里面的注解,以決定怎么去運(yùn)行類。掌握注解技術(shù)的要點(diǎn):如何定義注解如何反射注解,并根據(jù)反射的注解信息,決定如何去運(yùn)行類自定義Annotation定義新的Annotation類型使用@interface關(guān)鍵字聲明注解的屬性注解屬性的作用:原來寫在配置文件中的信息,可以通過注解的屬性進(jìn)行描述。Annotation的屬性聲明方式:Stringname();屬性類型:基本類型、String、Class、枚舉、注解及以上類型的一維數(shù)組類型屬性默認(rèn)值聲明方式:Stringname()default“xxx”;特殊屬性value:如果注解中有一個(gè)名稱value的屬性,那么使用注解時(shí)可以省略value=部分,如@MyAnnotation(“xxx")特殊屬性value[];JDK的元Annotation元Annotation指修飾Annotation的Annotation。JDK中定義了如下元Annotation:@Retention:只能用于修飾一個(gè)Annotation定義,用于指定該Annotation可以保留的域,@Rentention包含一個(gè)RetentionPolicy類型的成員變量,通過這個(gè)變量指定域。RetentionPolicy.CLASS:編譯器將把注解記錄在class文件中.當(dāng)運(yùn)行Java程序時(shí),JVM不會(huì)保留注解.這是默認(rèn)值RetentionPolicy.RUNTIME:編譯器將把注釋記錄在class文件中.當(dāng)運(yùn)行Java程序時(shí),JVM會(huì)保留注解.程序可以通過反射獲取該注釋RetentionPolicy.SOURCE:編譯器直接丟棄這種策略的注釋JDK的元Annotation2@Target:指定注解用于修飾類的哪個(gè)成員.@Target包含了一個(gè)名為value,類型為ElementType的成員變量。小練習(xí):將數(shù)據(jù)庫(kù)的配置采用注解實(shí)現(xiàn)JDK的元Annotation2@Documented:用于指定被該元Annotation修飾的Annotation類將被javadoc工具提取成文檔.@Inherited:被它修飾的Annotation將具有繼承性.如果某個(gè)類使用了被@Inherited修飾的Annotation,則其子類將自動(dòng)具有該注解提取Annotation信息JDK5.0在java.lang.reflect包下新增了AnnotationElement接口,該接口代表程序中可以接受注釋的程序元素當(dāng)一個(gè)Annotation類型被定義為運(yùn)行時(shí)Annotation后,該注釋才是運(yùn)行時(shí)可見,當(dāng)class文件被載入時(shí)保存在class文件中的Annotation才會(huì)被虛擬機(jī)讀取程序可以調(diào)用AnnotationElement對(duì)象的如下方法來訪問Annotation信息代理的概念和作用生活中的代理武漢人從武漢的代理商手中買聯(lián)想電腦和直接跑到北京來聯(lián)想總部買電腦,你覺得最終的主體業(yè)務(wù)目標(biāo)有什么區(qū)別?基本上一樣吧,都解決了核心問題,但是,一點(diǎn)區(qū)別都沒有嗎?從代理商那里買真得一點(diǎn)好處都沒有嗎?程序中的代理要為已存在的多個(gè)具有相同接口的目標(biāo)類的各個(gè)方法增加一些系統(tǒng)功能,例如,異常處理、日志、計(jì)算方法的運(yùn)行時(shí)間、事物管理等等,你準(zhǔn)備如何做?編寫一個(gè)與目標(biāo)類具有相同接口的代理類,代理類的每個(gè)方法調(diào)用目標(biāo)類的相同方法,并在調(diào)用方法時(shí)加上系統(tǒng)功能的代碼。如果采用工廠模式和配置文件的方式進(jìn)行管理,則不需要修改客戶端程序,在配置文件中配置使用目標(biāo)類還是代理類,這樣以后很容易切換,譬如,想要日志功能時(shí)就配置代理類,否則配置目標(biāo)類,這樣,增加系統(tǒng)功能很容易,以后運(yùn)行一段時(shí)間后,又想去掉系統(tǒng)功能也很容易。代理架構(gòu)圖
Client客戶端調(diào)用程序接口doSomethin()Target目標(biāo)類Proxy代理類doSomething(){//業(yè)務(wù)代碼}doSomething(){//前置系統(tǒng)代碼目標(biāo)對(duì)象.doSomething()//后置系統(tǒng)代碼}AOP系統(tǒng)中存在交叉業(yè)務(wù),一個(gè)交叉業(yè)務(wù)就是要切入到系統(tǒng)中的一個(gè)面。使用代理技術(shù)正好可以解決這種問題,代理是實(shí)現(xiàn)AOP功能的核心和關(guān)鍵技術(shù)動(dòng)態(tài)代理技術(shù)要為系統(tǒng)中的各種接口的類增加代理功能,那將需要太多的代理類,全部采用靜態(tài)代理方式,將是一件非常麻煩的事情!JVM可以在運(yùn)行期間動(dòng)態(tài)生成類的字節(jié)碼,這種動(dòng)態(tài)生成的類往往被用作代理類,即動(dòng)態(tài)代理類。JVM生成的動(dòng)態(tài)類必須實(shí)現(xiàn)一個(gè)或多個(gè)接口,所以,JVM生成的動(dòng)態(tài)類只能用作具有相同接口的目標(biāo)類的代理。CGLIB庫(kù)可以動(dòng)態(tài)生成一個(gè)類的子類,一個(gè)類的子類也可以用作該類的代理,所以,如果要為一個(gè)沒有實(shí)現(xiàn)接口的類生成動(dòng)態(tài)代理類,那么可以使用CGLIB庫(kù)。代理類的哥哥方法中通常除了要調(diào)用目標(biāo)的相應(yīng)方法和對(duì)外返回目標(biāo)返回的結(jié)果外,還可以在代理方法中的如下四個(gè)位置加上系統(tǒng)功能代碼:1、調(diào)用目標(biāo)方法之前2、調(diào)用目標(biāo)方法之后3、調(diào)用目標(biāo)方法前后4、在處理目標(biāo)方法異常的catch塊中分析JVM動(dòng)態(tài)生成的類創(chuàng)建實(shí)現(xiàn)了Collection接口的動(dòng)態(tài)類和查看其名稱,分析Proxy.getProxyClass方法的各個(gè)參數(shù)編碼列出動(dòng)態(tài)類中的所有構(gòu)造方法和參數(shù)簽名編碼列出動(dòng)態(tài)類中的所有方法和參數(shù)簽名創(chuàng)建動(dòng)態(tài)類的實(shí)例對(duì)象用反射獲得構(gòu)造方法編寫一個(gè)最簡(jiǎn)單的InvocationHandler類調(diào)用構(gòu)造方法創(chuàng)建動(dòng)態(tài)類的實(shí)例對(duì)象,并將編寫的InvocationHandler類的實(shí)例對(duì)象傳進(jìn)去打印創(chuàng)建的對(duì)象和調(diào)用對(duì)象的沒有返回值的方法和getClass方法,演示調(diào)用其他沒有返回值的方法報(bào)告了異常。將創(chuàng)建動(dòng)態(tài)類的實(shí)例對(duì)象的代理改成匿名內(nèi)部類的形式編寫??偨Y(jié)思考:讓JVM創(chuàng)建動(dòng)態(tài)類,需要給它提供哪些信息?Proxy.newProxyInstance()一步到位創(chuàng)建代理對(duì)象的實(shí)例北京傳智播客教育Tip:動(dòng)態(tài)代理明確兩個(gè)概念:代理對(duì)象存在的價(jià)值:主要用于攔截對(duì)真實(shí)業(yè)務(wù)對(duì)象的訪問。代理對(duì)象有什么方法?現(xiàn)在要生成某一個(gè)對(duì)象的代理對(duì)象,這個(gè)代理對(duì)象通常也要編寫一個(gè)類來生成,所以首先要編寫用于生成代理對(duì)象的類。如何編寫生成代理對(duì)象的類,兩個(gè)要素:代理誰如何生成代理對(duì)象代理誰?設(shè)計(jì)一個(gè)類變量,以及一個(gè)構(gòu)造函數(shù),記住代理類代理哪個(gè)對(duì)象。如何生成代理對(duì)象?設(shè)計(jì)一個(gè)方法生成代理對(duì)象(在方法內(nèi)編寫代碼生成代理對(duì)象是此處編程的難點(diǎn))北京傳智播客教育Tip:動(dòng)態(tài)代理Java提供了一個(gè)Proxy類,調(diào)用它的newInstance方法可以生成某個(gè)對(duì)象的代理對(duì)象,使用該方法生成代理對(duì)象時(shí),需要三個(gè)參數(shù):1.生成代理對(duì)象使用哪個(gè)類裝載器2.生成哪個(gè)對(duì)象的代理對(duì)象,通過接口指定3.生成的代理對(duì)象的方法里干什么事,由開發(fā)人員編寫handler接口的實(shí)現(xiàn)來指定。初學(xué)者必須理解,或不理解必須記住的2件事情:Proxy類負(fù)責(zé)創(chuàng)建代理對(duì)象時(shí),如果指定了handler(處理器),那么不管用戶調(diào)用代理對(duì)象的什么方法,該方法都是調(diào)用處理器的invoke方法。由于invoke方法被調(diào)用需要三個(gè)參數(shù):代理對(duì)象、方法、方法的參數(shù),因此不管代理對(duì)象哪個(gè)方法調(diào)用處理器的invoke方法,都必須把自己所在的對(duì)象、自己(調(diào)用invoke方法的方法)、方法的參數(shù)傳遞進(jìn)來。北京傳智播客教育Tip:動(dòng)態(tài)代理代理類publicObjectinvoke(Objectproxy,Methodmethod,Object[]args){ doSomething…….}voidrun(“aaa”){
}voideat(“bbb”){}invoke(this,run,”aaa”)invoke(this,eat,”bbb”)處理器代理對(duì)象voidrun(“aaa”)voideat(“bbb”)被代理對(duì)象北京傳智播客教育Tip:動(dòng)態(tài)代理應(yīng)用在動(dòng)態(tài)代理技術(shù)里,由于不管用戶調(diào)用代理對(duì)象的什么方法,都是調(diào)用開發(fā)人員編寫的處理器的invoke方法(這相當(dāng)于invoke方法攔截到了代理對(duì)象的方法調(diào)用)。并且,開發(fā)人員通過invoke方法的參數(shù),還可以在攔截的同時(shí),知道用戶調(diào)用的是什么方法,因此利用這兩個(gè)特性,就可以實(shí)現(xiàn)一些特殊需求,例如:攔截用戶的訪問請(qǐng)求,以檢查用戶是否有訪問權(quán)限、動(dòng)態(tài)為某個(gè)對(duì)象添加額外的功能。類加載器類加載器負(fù)責(zé)將.class文件(可能在磁盤上,也
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 保利地暖合同范例
- 小升初專項(xiàng)知識(shí)點(diǎn)課件
- 社區(qū)工作者培訓(xùn)心得體會(huì)模版
- 個(gè)體網(wǎng)絡(luò)借款合同范例
- 區(qū)塊鏈技術(shù)在遠(yuǎn)程教育資源共享中的價(jià)值
- 公司車輛采購(gòu)合同范例
- 兒童育嬰服務(wù)合同范例
- 書籍設(shè)計(jì)合同范例
- 個(gè)人房屋托管合同范例
- 2024年數(shù)控超精密車床項(xiàng)目資金籌措計(jì)劃書代可行性研究報(bào)告
- 農(nóng)村戶口分戶協(xié)議書(6篇)
- (部編版一年級(jí)下冊(cè))語文第七單元復(fù)習(xí)課件
- 新聞采訪與寫作(馬工程筆記)
- DB32∕T 1703-2011 科技成果轉(zhuǎn)化服務(wù)規(guī)范總則
- SQ-02-綠色食品種植產(chǎn)品調(diào)查表0308
- 視頻結(jié)構(gòu)化大數(shù)據(jù)平臺(tái)解決方案
- 麗聲北極星分級(jí)繪本第二級(jí)上Dinner for a Dragon 教學(xué)設(shè)計(jì)
- 活躍氣氛的開場(chǎng)小游戲「培訓(xùn)破冰前必備」
- 光伏發(fā)電項(xiàng)目安全專項(xiàng)投資估算方案
- 上海證券交易所(課堂PPT)
- 大學(xué)生物技術(shù)分析教材與教學(xué)設(shè)計(jì)
評(píng)論
0/150
提交評(píng)論