第一部分web筆記_第1頁(yè)
第一部分web筆記_第2頁(yè)
第一部分web筆記_第3頁(yè)
第一部分web筆記_第4頁(yè)
第一部分web筆記_第5頁(yè)
已閱讀5頁(yè),還剩15頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、day23 基礎(chǔ)加強(qiáng)今日內(nèi)容泛型注解Servlet3.0動(dòng)態(tài)類(lèi)加載器泛型1回顧泛型類(lèi)泛型類(lèi):具有一個(gè)或多個(gè)泛型變量的類(lèi)被稱(chēng)之為泛型類(lèi)。2泛型方法泛型方法的特點(diǎn):方法的參數(shù)中會(huì)使用泛型變量;方法的返回值中會(huì)使用泛型變量。調(diào)用泛型方法時(shí)無(wú)需指定泛型變量,編譯器會(huì)通過(guò)實(shí)際參數(shù)的類(lèi)型來(lái)識(shí)別泛型變量的類(lèi)型,上例中傳遞的參數(shù)為 String類(lèi)型,那么相當(dāng)于給泛型類(lèi)型 T 賦值為 String。public T get(T ts) return tsts.lengt / 2;String names =“zhangSan”, “l(fā)iSo”, “wangWu”;String name = get(names)

2、;public class A private T t; public A(T t) this.t = t;public T get() return t;3繼承(實(shí)現(xiàn))泛型類(lèi)(接口)繼承泛型類(lèi)需要為父類(lèi)的泛型變量賦值!就好比創(chuàng)建泛型類(lèi)的對(duì)象時(shí)需要給泛型變量賦值一樣。4通配符為了說(shuō)明通配符的作用,先看個(gè)例子:上面的調(diào)用都是編譯不通過(guò)的!這說(shuō)明想寫(xiě)一個(gè)即可以打印 list1,又可以打印 list2 的方法是不可能的!如果把 fun()方法的泛型參數(shù)去除,那么就 OK 了。即不使用泛型!上面代碼是沒(méi)有錯(cuò)了,但會(huì)有一個(gè)警告。警告的原因是你沒(méi)有使用泛型!Java用泛型。你可能會(huì)說(shuō),這里 TMD 根本就

3、不能使用泛型。希望大家都去使4.1通配符概述通配符就是專(zhuān)門(mén)處理這一問(wèn)題的。public sic void fun(List list) /會(huì)有一個(gè)警告List list1 = new ArrayList(); List list2 = new ArrayList(); fun(list1);fun(list2);public sic void fun(List list) List list1 = new ArrayList(); List list2 = new ArrayList(); fun(list1);/編譯不通過(guò)fun(list2);/編譯不通過(guò)List list1 = new A

4、rrayList(); List list2 = new ArrayList();/ 創(chuàng)建泛型類(lèi)對(duì)象List list = new ArrayList();/ 繼承泛型類(lèi) 1:子類(lèi)也是泛型類(lèi)public class MyList1 extends ArrayList / 繼承泛型類(lèi) 2:子類(lèi)不是泛型類(lèi)public class MyList2 extends ArrayList 上面代碼中的“?”就是一個(gè)通配符,它只能在“”中使用。造成不能把它從“”中拿出來(lái)。這時(shí)你可以向 fun()方法傳遞 List、List類(lèi)型的參數(shù)了。當(dāng)傳遞 List類(lèi)型的參數(shù)時(shí),表示給“?”賦值為 String;當(dāng)傳遞

5、List類(lèi)型的參數(shù)給 fun()方法時(shí),表示給“?”賦值為eger。4.2通配符的缺點(diǎn)帶有通配符的參數(shù)不能使用與泛型相關(guān)的方法,例如:list.add(“o”)編譯不通過(guò)。上面是處理了,但通配符也有它的缺點(diǎn)。在上面例子中,List list 參數(shù)中的通配符可以被賦任何值,但同時(shí)你也不知道通配符被賦了什么值。當(dāng)你不知道“?”是什么時(shí),會(huì)使你不能使用任何與泛型相關(guān)的方法。也就是說(shuō) fun()方法的參數(shù)list 不能再使用它的與泛型相關(guān)的方法了。例如:list.add(“o”)是錯(cuò)誤的,因?yàn)?List 類(lèi)的 add()方法的參數(shù)是 T 類(lèi)型,而現(xiàn)在你不知道 T 是什么類(lèi)型,你怎么去添加 String

6、 的東西給 list 呢?如果使用者在調(diào)用 fun()方法時(shí)傳遞的不是 List,而是 List時(shí),你添加 String 當(dāng)然是不可以的。當(dāng)然,還可以調(diào)用 list 的 get()方法。就算你不知道“?”是什么類(lèi)型,但它肯定是 Object 類(lèi)型的。所以你可以:Object o = list.get(0);4.3通配符的限制通配符只能出現(xiàn)在的定義中,而不能出現(xiàn)在創(chuàng)建對(duì)象中。例如:new ArrayList(),這是不可以的。ArrayList list = null,這是可以的。4.4帶有下邊界的通配符List list;其中表示通配符的下邊界,即“?”只能被賦值為 Number 或其子類(lèi)型。

7、當(dāng) fun()方法的參數(shù)為 List后,說(shuō)明你只能賦值給“?”Number 或 Number 的子類(lèi)型。雖然這多了一個(gè)限制,但也有好處,因?yàn)槟憧梢?list 的 get()方法了。就算你不知道“?”是什么類(lèi)型,但你知道它一定是 Number 或 Number 的子類(lèi)型。所以:Number num = list.get(0)是可以的。但是,還是不能調(diào)用 list.add()方法!public sic void fun(List list) fun(new ArrayList();/ok fun(new ArrayList();/ok fun(new ArrayList();/不 okpublic

8、 sic void fun(List list) 4.5帶有下邊界的通配符List list;其中表示通配符的下邊界,即“?”只能被賦值為eger 或其父類(lèi)型。這時(shí)再去調(diào)用 list.get()方法還是只能使用 Object 類(lèi)型來(lái)接收:Object o = list.get(0)。因?yàn)槟悴恢馈?”到底是eger 的哪個(gè)父類(lèi)。但是你可以調(diào)用 list.add()方法了,例如:list.add(neweger(100)是正確的。因?yàn)闊o(wú)論“?”是eger、Number、Object,list.add(neweger(100)都是正確的。通配符小結(jié)方法參數(shù)帶有通配符會(huì)更加通用;帶有通配符類(lèi)型的對(duì)象

9、,被限制了與泛型相關(guān)方法的使用;下邊界通配符:可以使用返回值為泛型變量的方法;上邊界通配符:可以使用參數(shù)為泛型變量的方法。5泛型父類(lèi)獲取子類(lèi)傳遞的類(lèi)型參數(shù)看一個(gè)例子:如果你需要在 A 類(lèi)中得到子類(lèi)給 T 賦值的類(lèi)型,那么可以使用下面的方法:public class A public A() ParameterizedType pType = (ParameterizedType)this.getClass().getGenericSuperclass(); Class clazz = (Class)pType.getActualTypeArguments()0;System.out.prln(

10、clazz.getName();public class A pubilc class B extends A public class C extends A public sic void fun(List list) fun(new ArrayList();/ok fun(new ArrayList();/ok fun(new ArrayList();/okfun(new ArrayList();/不 ok注解1注解的概述注釋你還記得么?開(kāi)個(gè)玩笑而已!注釋是給人看的,而注解是給程序看的!注釋是用來(lái)替代配置文件的!你回憶一下,以前總是要寫(xiě)一些配置文件,例如 web.xml 你還記得么?里面

11、要寫(xiě)和!讀配置文件呢?當(dāng)然是 Tomcat!寫(xiě)配置文件呢?當(dāng)然是來(lái)寫(xiě)了!在 Servlet3.0 中就可以使用使用注解來(lái)代替配置文件,開(kāi)發(fā)者就不用再寫(xiě)配置文件了,而是寫(xiě)注解,然后 Tomcat 來(lái)注解。注解也是類(lèi),需要定義了才能使用!分別在Servlet3.0 中有一個(gè)注解類(lèi)為WebServlet,然后就可以在Servlet 中使用WebServlet中使用這個(gè)注解了。這個(gè)注解就是用來(lái)替代了。然后 Tomcat 會(huì)通過(guò)反射來(lái)息!注解中的信2Java 中的注解Java 中的覺(jué)注解:Override:作用在方法上的注解。當(dāng)方法不是重寫(xiě)父類(lèi)的方法時(shí)會(huì)報(bào)錯(cuò); Deprecated:作用在方法上。標(biāo)記該

12、方法為作廢方法(已過(guò)時(shí)); SuppressWarnings:作用在方法上,壓制警告。3定義注解類(lèi)定義注解類(lèi)不能使用 class、enum,也不能使用erface,而是使用erface。4使用注解目標(biāo)注解可以作用在:類(lèi)(接口或枚舉)、屬性、方法、構(gòu)造器、包、參數(shù)、局部變量package cn.annocation;MyAnnpublic class MyClass MyAnnprivatea; MyAnnpublic MyClass() MyAnnpublic erface MyAnn5注解的屬性定義注解時(shí)也可以給出屬性其中 value 就是屬性!你可能會(huì)說(shuō),它是一個(gè)方法!沒(méi)錯(cuò),它是一個(gè)方法,

13、但性,因?yàn)榘阉?dāng)做屬性更加好理解。當(dāng)為注解指定屬性后,那么在使用注解時(shí)就必須要給屬性賦值了:非要稱(chēng)之為屬注解的屬性還可以有默認(rèn)值,在使用注解時(shí)就可以不給帶有默認(rèn)值的屬性賦值了。但沒(méi)有給出默認(rèn)值的屬性還是要賦值的。在使用注解時(shí),如果只給名為 value 的屬性賦值,那么可以不給出屬性的名稱(chēng)直接給出值。public erface MyAnn String value() default o world; value1() default 100;MyAnn()public class MyClass MyAnn(value=o)public class MyClass public erface

14、MyAnn String value() default o world; value1();MyAnn(value1=100)public class MyClass MyAnn(value1=100,value=o)public class MyClass public erface MyAnn String value();value1();public void fun1() MyAnnpublic void fun2(MyAnn String s) MyAnnn = 10;注解的屬性后面要有一對(duì)圓括號(hào),而且圓括號(hào)內(nèi)不能給出東西。就像是無(wú)參的方法一樣;注解的屬性類(lèi)型只能是:基本類(lèi)型、S

15、tring、Enum、Class、以上類(lèi)型的一維數(shù)組類(lèi)型;注解的屬性可以有默認(rèn)值,例如:a() default 100;數(shù)組的屬性默認(rèn)值: arr() default 1,2,3,這里不能使用 new使用注解時(shí),在給數(shù)組屬性賦值時(shí)的格式:MyAnn(arr=1,2,3);1,2,36注解的作用目標(biāo)在定義注解時(shí)可以限制注解的作用目錄!例如讓注解只能作用在類(lèi)和方法上。這需要使用元注解:。該注解有一個(gè)屬性 value,類(lèi)型為 ElementType,它是枚舉類(lèi)型。在定義注解時(shí),可以使用注解來(lái)限制注解的作用目標(biāo):這樣 MyAnn 就只能作用在類(lèi)和方法上的!其中 ElementType.TYPE 表示類(lèi)

16、和接口。MyAnn()public class MyClass (ElementType.TYPE, ElementType.METHOD)public erface MyAnn public erface ElementType value();public enum ElementType TYPE,FIELD,METHOD,PARAMETED,CONSTRUCTOR,LOCAL_VARIABLE,ANNOCATION_TYPE,PACKAGEMyAnn(value1=200)public class MyClass MyAnn(value=o,value1=200)public clas

17、s MyClass MyAnn(o annocation)public class MyClass MyAnn(300)public class MyClass MyAnn(o,value1=200)public class MyClass 7注解的保留策略注解的保留策略是指,注解是只保留在源代碼上,還是保留到 class 文件上,再或者是類(lèi)在運(yùn)行時(shí),可以被類(lèi)加載器加載到內(nèi)存中。如果希望注解被反射,那么注解就要保留到運(yùn)行時(shí),而不是源代碼或類(lèi)文件上。指定注解的保留策略需要使用元注解Retention,它有一個(gè) value 屬性,類(lèi)型為 RetentionPolicy類(lèi)型,RetentionPol

18、icy 是枚舉類(lèi)型:下面代碼是指定注解保留到運(yùn)行時(shí)8通過(guò)反射注解注解需要使用反射來(lái)完成Retention(RetentionPolicy.RUNTIME)(ElementType.TYPE, ElementType.METHOD)public erface MyAnn String value() default o; value1() default 100;MyAnn(value=o world, value1=200)public class MyClass privatea;MyAnn(myMethod)Retention(RetentionPolicy.RUNTIME)(Elemen

19、tType.TYPE, ElementType.METHOD)public erface MyAnn String value() default o; value1() default 100;public erface Retention RetentionPolicy value();public enum RetentionPolicy SOURCE, CLASS, RUNTIMEMyAnn()privatea;MyAnn()public void fun() Servlet3.0 新特性1Servlet3.0 新特性概述Servlete3.0 的主要新特性如下三部分:使用WebSer

20、vlet、WebFilter、WebListener 三個(gè)注解來(lái)替代 web.xml 文件中的 Servlet、 Filter、Listener 的配置;Servlet 異步處理:當(dāng) Servlet 處理比較費(fèi)時(shí)時(shí),這會(huì)讓客戶(hù)感覺(jué)到很卡。當(dāng)使用異常處理時(shí)可以把已經(jīng)處理好的內(nèi)容先一步響應(yīng)給客戶(hù)端瀏覽器,然后使用另一個(gè)線程來(lái)完成費(fèi)時(shí)的操作,也就是把內(nèi)容一部分一部分的顯示出來(lái);上傳組件:不用再使用 fileupload 等第便。的上傳組件,使用 Servlet3.0 的上傳組件會(huì)更方2WebServlet、WebFilter、WebListenerWebServlet(urlPatterns=/AS

21、ervlet, initParams=WebInitParam(name=paramName,value=paramValue), loadOnStartup=1)public class AServlet extends HttpServlet public void init(ServletConfig config) throws ServletException System.out.prln(config.getInitParameter(paramName);public void doGet(HttpServletRequest request, HttpServletRespo

22、nsepublic void fun() public class Demo1 public sic void main(String args) throws Exception Class clazz = MyClass.class;MyAnn myAnn = (MyAnn) clazz.getAnnoion(MyAnn.class); System.out.prln(myAnn.value();System.out.prln(myAnn.value1();Method method = clazz.getMethod(fun);MyAnn myAnn1 = method.getAnnoi

23、on(MyAnn.class); System.out.prln(myAnn1.value();System.out.prln(myAnn1.value1();3Servlet 異步處理Servlet 異步處理就是讓 Servlet 在處理費(fèi)時(shí)的請(qǐng)求時(shí)不要阻塞,而是一部分一部分的顯示。也就是說(shuō),在使用 Servlet 異步處理之后,頁(yè)面可以一部分一部分的顯示數(shù)據(jù),而不是一直卡,等到請(qǐng)求響應(yīng)結(jié)束后一起顯示。在使用異步處理之前,一定要在WebServlet 注解中給出 asyncSupported=true,不然默認(rèn) Servlet是不支持異步處理的。如果存在過(guò)濾器,也要設(shè)置WebFilter 的

24、 asyncSupportedt=true。使用異步處理大致可以分為兩步:Servlet 正常響應(yīng)數(shù)據(jù);WebServlet(urlPatterns = /MyServlet, asyncSupported=true)public class MyServlet extends HttpServlet response)throws ServletException, IOException request.setCharacterEncoding(utf-8); response.setContentType(text/html;charset=utf-8); response.getWri

25、ter().pr(o World!);WebFilter(urlPatterns=/*, dispatcherTypes=DispatcherType.REQUEST, DispatcherType.FORWARD) public class AFilter implements Filter public void destroy() public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException Sys

26、tem.out.prln(start filter); chain.doFilter(request, response); System.out.prln(end filter);public void init(FilterConfig fConfig) throws ServletException WebListener()public class AListener implements ServletContextListener public void contextDestroyed(ServletContextEvent arg0) System.out.prln(服務(wù)器關(guān)閉

27、了);public void contextInitialized(ServletContextEvent arg0) System.out.prln(服務(wù)器啟動(dòng)了);Servlet 異常響應(yīng)數(shù)據(jù)。在 Servlet 正常響應(yīng)數(shù)據(jù)時(shí),沒(méi)什么可說(shuō)的,可通知 response.getWriter().pr()來(lái)向客戶(hù)端輸出,但輸出后要使用 response.getWriter().flush()刷新,不然數(shù)據(jù)只是在緩沖區(qū)中,不能向客戶(hù)端發(fā)送數(shù)據(jù)的。異步響應(yīng)數(shù)據(jù)需要使用 request.startAsync()方法獲取 AsyncContext 對(duì)象。然后調(diào)用 AsyncContext對(duì)象的 sta

28、rt()方法啟動(dòng)異步響應(yīng),start()方法需要一個(gè) Runnable 類(lèi)型的參數(shù)。在 Runnable 的 run()方法中給出異步響應(yīng)的代碼。注意在異步處理線程中使用 response 做響應(yīng)后,要使用 response.getWriter().flush()來(lái)刷新流,不然數(shù)據(jù)是不能響應(yīng)到客戶(hù)端瀏覽器的。Tomcat 需要知道異步響應(yīng)是否結(jié)束,如果響應(yīng)不結(jié)束,雖然客戶(hù)端瀏覽器會(huì)看到響應(yīng)的數(shù)據(jù),但是鼠標(biāo)上只是有個(gè)圈圈的的轉(zhuǎn)啊轉(zhuǎn)的,表示還沒(méi)有結(jié)束響應(yīng)。Tomcat 會(huì)等待到超時(shí)為止,這個(gè)超時(shí)的時(shí)間可以通過(guò) AsyncContext 類(lèi)的 getTimeout()方法獲取,Tomcat 默認(rèn)為

29、20000 毫秒。當(dāng)然也可以通過(guò) setTimeOut()方法設(shè)置,以毫秒為。ac.setTimeout(1000*10)。如果異步線程已經(jīng)結(jié)束了響應(yīng),那么可以在異步線程中調(diào)用Tomcat 就知道異步線程已經(jīng)完成了工作了。plete()方法,這樣WebServlet(urlPatterns = /AServlet, asyncSupported=true)public class AServlet extends HttpServlet public void doGet(HttpServletRequest request, HttpServletResponse response)thro

30、ws ServletException, IOException response.setContentType(text/html;charset=utf-8); PrWriter out = response.getWriter();out.prln(Servlet begin );asyncContext.start(new Runnable() public void run() for(char i = a; i = z; i+) try Thread.sleep(100); asyncContext.getResponse().getWriter().pr(i +&;);async

31、Context.getResponse().getWriter().flush(); catch (Exception e) e.prStackTrace();plete(););AsyncContext ac = request.startAsyncContext(request, response); ac.start(new Runnable() );out.pr out.pr out.pr out.pr out.pr out.pr out.pr out.pr out.pr out.pr out.pr out.pr ut.prln(Servlet ln(Servlet ln

32、(Servlet ln(Servlet ln(Servlet ln(Servlet ln(Servlet ln(Servlet ln(Servlet ln(Servlet ln(Servlet ln(Servlet ln(Servletln(Servletbegin begin begin begin begin begin begin begin begin begin begin begin beginbegin););););););););););););););out.flush();final AsyncContext asyncContext = request.startAsy

33、nc(request, response);asyncContext.setTimeout(1000 * 20); asyncContext.start(new Runnable() public void run() try Thread.sleep(1000);asyncContext.getResponse().getWriter().pr(馬上開(kāi)始+);asyncContext.getResponse().getWriter().flush(); Thread.sleep(2000); catch (Exception e1) for(char i = a; i = z; i+) tr

34、y Thread.sleep(100); asyncContext.getResponse().getWriter().pr(i +&;);asyncContext.getResponse().getWriter().flush(); catch (Exception e) e.prStackTrace();plete(););/ asyncContext.start(businessHandleThread);/ 也可以用這種方法啟動(dòng)異步線程4文件上傳Servlet3.0 提供了文件上傳的處理方案。只需要在 Servlet 上添加MultipartConfig 注解即可。當(dāng)然也可以為Mult

35、ipartConfig 注解指定屬性值,它有四個(gè)屬性:filesizeThreshold:指定緩存的大小,當(dāng)超出這個(gè)大小后,文件會(huì)保存到磁盤(pán)上; String location:指定臨時(shí)文件的目錄;long maxFilesize:指定上會(huì)拋出異常;個(gè)文件的大小限制,如果上傳的誰(shuí)的超出了這個(gè)大小,那么就long maxRequestSize:指定整個(gè)表單的大小限制。當(dāng)在 Servlet 上使用了MultipartConfig 注解后,那么就可以使用 request.getPart(“fieldName”)來(lái)獲取的內(nèi)容,其中 Part 表示一個(gè)文件表單項(xiàng)。用戶(hù)名:WebServlet(urlPa

36、tterns=/UploadServlet) MultipartConfig(maxFileSize=1024 * 1024) public claploadServlet extends HttpServlet public void dot(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException request.setCharacterEncoding(utf-8); response.setContentType(text/html;charset=utf-

37、8);String username = request.getParameter(username); response.getWriter().pr(size: + username + );Part part = request.getPart(file1);response.getWriter().pr(size: + part.getSize() + ); response.getWriter().pr(type: + part.getContentType() + ); response.getWriter().pr(name: + part.getName() + );Strin

38、g name = part.getHeader(content-disition);WebServlet(urlPatterns=/UploadServlet) MultipartConfig(maxFileSize=1024)public claploadServlet extends HttpServlet out.prln(Servlet end );動(dòng)態(tài)1學(xué)習(xí)動(dòng)態(tài)的目的動(dòng)態(tài)技術(shù)都是在框架中使用,例如:Struts1、Struts2、Spring 和 Hibernate 中都使用了動(dòng)態(tài)技術(shù)。如果你不想自己寫(xiě)個(gè)框架,那么你基本上是用上不動(dòng)態(tài)技術(shù)的。學(xué)習(xí)動(dòng)態(tài)習(xí)框架打基礎(chǔ)!技術(shù)的目的是為了更好

39、的理解框架的原理,也就是說(shuō)是為了將來(lái)學(xué)動(dòng)態(tài)技術(shù)有點(diǎn)小難度!而且明白了動(dòng)態(tài)技術(shù)可能一時(shí)也想不到他適合在什么情況下使用它。這些東西都會(huì)在學(xué)習(xí)框架時(shí)漸漸明白。2運(yùn)行時(shí)實(shí)現(xiàn)指定的接口想實(shí)現(xiàn)某個(gè)接口,你需要寫(xiě)一個(gè)類(lèi),然后在類(lèi)名字的后面給出“implements”實(shí)現(xiàn)某個(gè)接口:接口。這才是上面的代碼對(duì)來(lái)說(shuō)沒(méi)新鮮感,的是動(dòng)態(tài)技術(shù)可以通過(guò)一個(gè)方法調(diào)用就可以生成一個(gè)對(duì)指定接口的實(shí)現(xiàn)類(lèi)對(duì)象。publicerface Myerface void fun1();void fun2();public class MyerfaceImpl implements Myerface public void fun1() Sy

40、stem.out.prln(fun1();public void fun2() System.out.prln(fun2();String fileNameTmp = name.substring(name.indexOf(filename=)+10); String fileName = fileNameTmp.substring(0,fileNameTmp.indexOf();System.out.prln(fileName: + fileName);String savepath = this.getServletContext().getRealPath(/uploads); part

41、.write(savepath + / + fileName);上面代碼中,Proxy 類(lèi)的靜態(tài)方法 newProxyInstance()方法生成了一個(gè)對(duì)象,這個(gè)對(duì)象實(shí)現(xiàn)了 cs數(shù)組中指定的接口。沒(méi)錯(cuò),返回值 mi 是 My erface 接口的實(shí)現(xiàn)類(lèi)。你不要問(wèn)這個(gè)類(lèi)是哪個(gè)類(lèi),你只需要知道 mi 是 My erface 接口的實(shí)現(xiàn)類(lèi)就可以了。你現(xiàn)在也不用去管 loader 和 h 這兩個(gè)參數(shù)是什么東東,你只需要知道,Proxy 類(lèi)的靜態(tài)方法 newProxyInstance()方法返回的方法是實(shí)現(xiàn)了指定接口的實(shí)現(xiàn)類(lèi)對(duì)象,甚至你都沒(méi)有看見(jiàn)實(shí)現(xiàn)類(lèi)的代碼。動(dòng)態(tài)就是在運(yùn)行時(shí)生成一個(gè)類(lèi),這個(gè)類(lèi)會(huì)實(shí)現(xiàn)你指

42、定的一組接口,而這個(gè)類(lèi)沒(méi)有.java 文件,是在運(yùn)行時(shí)生成的,你也不用去關(guān)心它是什么類(lèi)型的,你只需要知道它實(shí)現(xiàn)了哪些接口即可。3newProxyInstance()方法的參數(shù)Proxy 類(lèi)的 newInstance()方法有三個(gè)參數(shù):ClassLoader loader:它是類(lèi)加載器類(lèi)型,你不用去理睬它,你只需要知道怎么可以獲得它就可以了:My erface.class.getClassLoader()就可以獲取到 ClassLoader 對(duì)象,沒(méi)錯(cuò),只要你有一個(gè) Class 對(duì)象就可以獲取到 ClassLoader 對(duì)象;erfa:指定 newProxyInstance()方法返回的對(duì)象要實(shí)

43、現(xiàn)哪些接口,沒(méi)錯(cuò),可以指Class定多個(gè)接口,例如上面例子只只指定了一個(gè)接口:Class cs = Myerface.class;InvocationHandler h:它是最重要的一個(gè)參數(shù)!它是一個(gè)接口!它的名字叫調(diào)用處理器!你想,上面例子中 mi 對(duì)象是Myerface 接口的實(shí)現(xiàn)類(lèi)對(duì)象,那么它一定是可以調(diào)用 fun1()和 fun2()方法了,難道你不想調(diào)用一下 fun1()和 fun2()方法么,它會(huì)執(zhí)行些什么東東呢?其實(shí)無(wú)論你調(diào)用對(duì)象的什么方法,它都是在調(diào)用 InvocationHandler 的 invoke()方法!InvocationHandler 接口只有一個(gè)方法,即 inv

44、oke()方法!它是對(duì)對(duì)象所有方法的唯一實(shí)現(xiàn)。也就是說(shuō),無(wú)論你調(diào)用對(duì)象上的哪個(gè)方法,其實(shí)都是在調(diào)用 InvocationHandler 的 invoke()方法。想象中的類(lèi):public sic void main(String args) Class cs = Myerface.class;ClassLoader loader = Myerface.class.getClassLoader(); InvocationHandler h = new InvocationHandler() public Object invoke(Object proxy, Method method, Obj

45、ect args)throws Throwable System.out.prln(無(wú)論你調(diào)用對(duì)象的什么方法,其實(shí)都是在調(diào)用invoke().);return null;Myerface mi = (Myerface)Proxy.newProxyInstance(loader, cs, h); mi.fun1();mi.fun2();Class cs = Myerface.class;Myerface mi = (Myerface)Proxy.newProxyInstance(loader, cs, h);注意,X 類(lèi)是用來(lái)理解對(duì)象與 InvocationHandler 之間的關(guān)系的,但它是不

46、存在的類(lèi)。是想象出來(lái)的!也就是說(shuō),它是用來(lái)說(shuō)明,無(wú)論你調(diào)用對(duì)象的哪個(gè)方法,最終調(diào)用的都是調(diào)用處理器的 invoke()方法。4InvocationHandler 的 invoke()方法InvocationHandler 的 invoke()方法的參數(shù)有三個(gè):Object proxy:它;對(duì)象,也就是 Proxy.newProxyInstance()方法返回的對(duì)象,通常用不上Method method:表示當(dāng)前被調(diào)用方法的反射對(duì)象,例如 mi.fun1(),那么 method 就是 fun1()方法的反射對(duì)象;Object args:表示當(dāng)前被調(diào)用方法的參數(shù),當(dāng)然 mi.fun1()這個(gè)調(diào)用是

47、沒(méi)有參數(shù)的,所以 args是一個(gè)零長(zhǎng)數(shù)組。最后的是 invoke()方法的返回值為 Object 類(lèi)型,它表示當(dāng)前被調(diào)用的方法的返回值,當(dāng)然mi.fun1()方法是沒(méi)有返回值的,所以 invoke()返回的就必須是 null 了。public sic void main(String args) Class cs = Myerface.class;ClassLoader loader = Myerface.class.getClassLoader(); InvocationHandler h = new InvocationHandler() public Object invoke(Obje

48、ct proxy, Method method, Object args)throws Throwable System.out.prln(當(dāng)前調(diào)用的方法是: + method.getName();return null;Myerface mi = (Myerface)Proxy.newProxyInstance(loader, cs, h); mi.fun1();mi.fun2();當(dāng)前調(diào)用的方法是:fun1class X implements Myerface private InvocationHandler h; public X(InvocationHandler h) this.h

49、 = h;public void fun1() h.invoke();public void fun2() h.invoke();5動(dòng)態(tài)動(dòng)態(tài)的用途的用途與裝飾模式很相似,就是為了對(duì)某個(gè)對(duì)象進(jìn)行增強(qiáng)。所有使用裝飾者模式的案例都可以使用動(dòng)態(tài)來(lái)替換。下面用一個(gè)例子來(lái)說(shuō)明動(dòng)態(tài)的用途!來(lái)寫(xiě)一個(gè) Waiter 接口,它只有一個(gè) serve()方法。MyWaiter 是 Waiter 接口的實(shí)現(xiàn)類(lèi):現(xiàn)在要對(duì) MyWaiter 對(duì)象進(jìn)行增強(qiáng),要讓它在服務(wù)之前以及服務(wù)之后添加禮貌用語(yǔ),即在服務(wù)之前說(shuō)“您好!”,在服務(wù)之后說(shuō):“很高興為您服務(wù)!”。public class MainApp1 public sic

50、void main(String args) ClassLoader loader = MainApp1.class.getClassLoader(); Class cs = Waiter.class;Waiter= new MyWaiter();MyInvocationHandler h = new MyInvocationHandler(); Waiter waiter = (Waitroxy.newProxyInstance(loader, cs, h); waiter.serve();class MyInvocationHandler implements InvocationHand

51、ler public Waiter;public MyInvocationHandler(Waiter) this.=;public Object invoke(Object proxy, Method method, Object args)throws Throwable System.out.prln(您好!);Object result = method.invoke(, args); System.out.prln(很高興為您服務(wù)!);return result;publicerface Waiter public void serve();public class MyWaiter

52、 implements Waiter public void serve() System.out.prln(服務(wù).);當(dāng)前調(diào)用的方法是:fun2類(lèi)加載器1類(lèi)加載器類(lèi)加載器就是用來(lái)加載類(lèi)的東西!類(lèi)加載器也是一個(gè)類(lèi):ClassLoader類(lèi)加載器可以被加載到內(nèi)存,是通過(guò)類(lèi)加載器完成的!Java 提供了三種類(lèi)加載器,分別是:bootstrap classloader:引導(dǎo)類(lèi)加載器,加載 rt.jar 中的類(lèi); sun.misc.Launcher$ExtClassLoader:擴(kuò)展類(lèi)加載器,加載 lib/ext 目錄下的類(lèi); sun.misc.Launcher$AppClassLoader:系統(tǒng)類(lèi)加

53、載器,加載 CLASSPATH 下的類(lèi),即寫(xiě)的類(lèi),以及第提供的類(lèi)。通常情況下,Java 中所有類(lèi)都是通過(guò)這三個(gè)類(lèi)加載器加載的。類(lèi)加載器之間存在上下級(jí)關(guān)系,系統(tǒng)類(lèi)加載器的是引導(dǎo)類(lèi)加載器。是擴(kuò)展類(lèi)加載器,而擴(kuò)展類(lèi)加載器的2JVM 眼中的相同的類(lèi)在 JVM 中,不可能存在一個(gè)類(lèi)被加載兩次的事情!一個(gè)類(lèi)如果已經(jīng)被加載了,當(dāng)再次試圖加載這個(gè)類(lèi)時(shí),類(lèi)加載器會(huì)先去查找這個(gè)類(lèi)是否已經(jīng)被加載過(guò)了,如果已經(jīng)被加載過(guò)了,就不會(huì)再去加載了。但是,如果一個(gè)類(lèi)使用不同的類(lèi)加載器去加載是可以出現(xiàn)多次加載的情況的!也就是說(shuō),在 JVM眼中,相同的類(lèi)需要有相同的 class 文件,以及相同的類(lèi)加載器。當(dāng)一個(gè) class 文件,

54、被不同的類(lèi)加載器加載了,JVM 會(huì)認(rèn)識(shí)這是兩個(gè)不同的類(lèi),這會(huì)在 JVM 中出現(xiàn)兩個(gè)相同的 Class 對(duì)象!甚至?xí)霈F(xiàn)類(lèi)型轉(zhuǎn)換異常!3類(lèi)加載器的模式當(dāng)系統(tǒng)類(lèi)加載器去加載一個(gè)類(lèi)時(shí),它首先會(huì)讓類(lèi)加載器也會(huì)讓它的引導(dǎo)類(lèi)加載器去加載類(lèi)。如果去加載,即讓擴(kuò)展類(lèi)加載器去加載類(lèi),擴(kuò)展沒(méi)有加載成功,那么再由自己去加載!例如自己寫(xiě)的類(lèi),一定是存放到 CLASSPATH 中,那么一定是由系統(tǒng)類(lèi)加載器來(lái)加載。當(dāng)系統(tǒng)類(lèi)加載器來(lái)加載類(lèi)時(shí),它首先把加載的任務(wù)交給擴(kuò)展類(lèi)加載去,如果擴(kuò)展類(lèi)加載器加載成功了,那么系統(tǒng)類(lèi)加載器就不會(huì)再去加載。這就是模式了!相同的道理,擴(kuò)展類(lèi)加載器也會(huì)把加載類(lèi)的任務(wù)交給它的“”,即引導(dǎo)類(lèi)加載器,引導(dǎo)類(lèi)加載器加載成功,那么擴(kuò)展類(lèi)加載器也就不會(huì)再去加載了。引導(dǎo)類(lèi)加載器是用 C 語(yǔ)言寫(xiě)的,是 JVM 的一部分,它是最上層的類(lèi)加載器了,所以它就沒(méi)有“了”。它只負(fù)責(zé)去加載“人”,即 JDK中的類(lèi),但知道類(lèi)不是自己寫(xiě)的類(lèi),所以它加載失敗。當(dāng)擴(kuò)展類(lèi)加載器發(fā)現(xiàn)“”不能加載類(lèi),它就開(kāi)始加載工作了,它加載的是 libext 目錄下的jar 文件,當(dāng)然,它也會(huì)加載失敗,所以最終還是由系統(tǒng)類(lèi)加載器在 CLASSPATH 中去加載,最終由系統(tǒng)類(lèi)加載器加載到了類(lèi)。模式保證了 JDK 中的類(lèi)一定是由引導(dǎo)類(lèi)加載加載的!這就不會(huì)出現(xiàn)多個(gè)版本的類(lèi),這也是模式的好處。3自定義類(lèi)加載器也可以通過(guò)繼承 ClassLoad

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論