棲息地

          家園

          2010年7月2日 #

          解決Jsp頁(yè)面URL中傳遞參數(shù)亂碼的方法

          Jsp頁(yè)面在URL中傳遞參數(shù)會(huì)出現(xiàn)亂碼可以采用以下方法解決:一、使用更改Tomcat的方法。二、使用JSP的scriptLet view plaincopy to clipboardprint?三、使用自定義JSTL。

          Jsp頁(yè)面在URL中傳遞參數(shù)會(huì)出現(xiàn)亂碼

          解決方法如下:

          一、使用更改Tomcat的方法。這個(gè)方法簡(jiǎn)單,但是需要改動(dòng)的地方是服務(wù)器軟件級(jí)別的,如果稍微變動(dòng)系統(tǒng)將無法正確轉(zhuǎn)碼,移植性不高。

          1、來到tomcat目錄,找到conf目錄下的server.xml問價(jià),打開,找到<Connector>標(biāo)簽,在最后添加URIEncoding=’GBK’,效果如下:

          view plaincopy to clipboardprint?

          <Connector

          port="8080"maxThreads="150"minSpareThreads="25"maxSpareThreads="75"

          enableLookups="false"redirectPort="8443"acceptCount="100"

          debug="0"connectionTimeout="20000"

          disableUploadTimeout="true"URIEncoding=″GBK″/>

          <Connectorport="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"enableLookups="false" redirectPort="8443" acceptCount="100"debug="0" connectionTimeout="20000"disableUploadTimeout="true" URIEncoding=″GBK″/>

          這種方法對(duì)get這個(gè)方法測(cè)試成功。

          2、在每個(gè)Jsp頁(yè)面添加如下代碼

          view plaincopy to clipboardprint?

          <%@pagepageEncoding=”gb2312″%>

          <%@pagecontentType=”text/html;charset=gb2312″%>

          <%request.setCharacterEncoding(”gb2312″);%>

          <%@ page pageEncoding=”gb2312″%><%@ page contentType=”text/html;charset=gb2312″%><%request.setCharacterEncoding(”gb2312″);%>

          編碼方式也可以改成GBK,支持繁體中文。重啟Tomcat,這一步很重要,否則可能看不到效果。

          這種方法對(duì)post測(cè)試成功。建議兩種同步使用。

          二、使用JSP的scriptLet

          view plaincopy to clipboardprint?

          <%=newString(elValue.getBytes("iso-8859-1"),"GBK")%>

          <%=new String(elValue.getBytes("iso-8859-1"),"GBK")%>

          三、使用自定義JSTL

          這是我們的重點(diǎn)所在,這里要詳細(xì)說明.

          第一,編寫自定義標(biāo)簽

          第二編寫tag文件

          第三部署tag文件

          第四使用吧;)很簡(jiǎn)單的.

          posted @ 2010-07-02 10:34 drecry 閱讀(211) | 評(píng)論 (0)編輯 收藏

          2010年6月11日 #

          (轉(zhuǎn))方法重載與方法覆蓋(重寫)

          方法覆蓋必須滿足下列條件
          (1) 子類的方法的名稱及參數(shù)必須和所覆蓋的方法相同
          (2) 子類的方法返回類型必須和所覆蓋的方法相同
          (3) 子類方法不能縮小所覆蓋方法的訪問權(quán)限
          (4) 子類方法不能拋出比所覆蓋方法更多的異常
          重載方法必須滿足下列條件
          (1) 方法名必須相同
          (2) 方法的參數(shù)簽名必須相同
          (3) 方法的返回類型和方法的修飾符可以不相同
          順便說說方法覆蓋和重載的區(qū)別
          初次見到這兩個(gè)單詞并沒有什么特別的感覺,但是時(shí)間長(zhǎng)了,卻發(fā)現(xiàn)書上一會(huì)兒用override,一會(huì)兒又用overload,搞得我的迷迷糊。于是就做了個(gè)總結(jié),希望能對(duì)和我一樣對(duì)這兩個(gè)概念模糊不清的網(wǎng)友有一個(gè)幫助。
          override可以翻譯為覆蓋,從字面就可以知道,它是覆蓋了一個(gè)方法并且對(duì)其重寫,以求達(dá)到不同的作用。對(duì)我們來說最熟悉的覆蓋就是對(duì)接口方法的實(shí)現(xiàn),在接口中一般只是對(duì)方法進(jìn)行了聲明,而我們?cè)趯?shí)現(xiàn)時(shí),就需要實(shí)現(xiàn)接口聲明的所有方法。除了這個(gè)典型的用法以外,我們?cè)诶^承中也可能會(huì)在子類覆蓋父類中的方法。在覆蓋要注意以下的幾點(diǎn):
          1、覆蓋的方法的標(biāo)志必須要和被覆蓋的方法的標(biāo)志完全匹配,才能達(dá)到覆蓋的效果;
          2、覆蓋的方法的返回值必須和被覆蓋的方法的返回一致;
          3、覆蓋的方法所拋出的異常必須和被覆蓋方法的所拋出的異常一致,或者是其子類;
          4、被覆蓋的方法不能為private,否則在其子類中只是新定義了一個(gè)方法,并沒有對(duì)其進(jìn)行覆蓋。
          overload對(duì)我們來說可能比較熟悉,可以翻譯為重載,它是指我們可以定義一些名稱相同的方法,通過定義不同的輸入?yún)?shù)來區(qū)分這些方法,然后再調(diào)用時(shí),VM就會(huì)根據(jù)不同的參數(shù)樣式,來選擇合適的方法執(zhí)行。在使用重載要注意以下的幾點(diǎn):
          1、在使用重載時(shí)只能通過不同的參數(shù)樣式。例如,不同的參數(shù)類型,不同的參數(shù)個(gè)數(shù),不同的參數(shù)順序(當(dāng)然,同一方法內(nèi)的幾個(gè)參數(shù)類型必須不一樣,例如可以是fun(int,float),但是不能為fun(int,int));
          2、不能通過訪問權(quán)限、返回類型、拋出的異常進(jìn)行重載;
          3、方法的異常類型和數(shù)目不會(huì)對(duì)重載造成影響;
          4、對(duì)于繼承來說,如果某一方法在父類中是訪問權(quán)限是priavte,那么就不能在子類對(duì)其進(jìn)行重載,如果定義的話,也只是定義了一個(gè)新方法,而不會(huì)達(dá)到重載的效果。
          下面是對(duì)override和overload的測(cè)試程序,其中注釋中的內(nèi)容都是會(huì)產(chǎn)生編譯錯(cuò)誤的代碼,我們將注釋去掉,看看在編譯時(shí)會(huì)產(chǎn)生什么效果。
          //對(duì)overload測(cè)試的文件:OverloadTest.java
          publicnewOverrideTest1();
          try{
          test.fun();
          test.fun1();
          }catch(Exceptione){}
          }
          }
          classOverrideTest1extendsOverrideTest{
          //以下正常Override
          publicvoidfun()throwsTestException2{
          System.out.println("funinOverrideTest1");
          }
          //不能Override父類中的方法,因?yàn)樗x了不同的異常類型和
          //返回值。
          //publicintfun()throwsTestException1{
          //System.out.println("methodfuninTest");
          //return1;
          //}
          //不能Override父類中的方法,因?yàn)樗鼟伋隽吮雀割愔蟹欠ǚ秶?
          //更大的異常。
          //publicvoidfun()throwsException{
          //System.out.println("funinOverrideTest1");
          //}
          //這個(gè)方法并沒有Override父類中的fun1方法,因?yàn)檫@個(gè)方法在
          //父類是private類型,所以這里只是相當(dāng)于定義了一個(gè)新方法。
          publicvoidfun1(){
          System.out.println("methodfun1inTest");
          }
          }
          classTestExceptionextendsException{
          publicTestException(Stringmsg){
          super(msg);
          }
          }
          classTestException1extendsTestException{
          publicTestException1(Stringmsg){
          super(msg);
          }
          }
          classTestException2extendsTestException{
          publicTestException2(Stringmsg){
          super(msg);
          }
          } 

          參考資料:http://zhidao.baidu.com/question/1996221.html
           

          posted @ 2010-06-11 21:35 drecry 閱讀(451) | 評(píng)論 (0)編輯 收藏

          2010年3月25日 #

          JAVA面試題(五)

          5.1  是否可以繼承String類?

              String類是final類故不可以繼承。

              5.2  swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

              switch(expr1)中,expr1是一個(gè)整數(shù)表達(dá)式。因此傳遞給 switch 和 case 語(yǔ)句的參數(shù)應(yīng)該是 int、 short、 char 或者 byte.long,string 都不能作用于swtich.

              5.3  try {}里有一個(gè)return語(yǔ)句,那么緊跟在這個(gè)try后的finally {}里的code會(huì)不會(huì)被執(zhí)行,什么時(shí)候被執(zhí)行,在return前還是后?

              會(huì)執(zhí)行,在return前執(zhí)行。

              5.4  編程題: 用最有效率的方法算出2乘以8等於幾?

              2 << 3

              5.5  兩個(gè)對(duì)象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對(duì)不對(duì)?

              不對(duì),有相同的hash code.

              5.6  當(dāng)一個(gè)對(duì)象被當(dāng)作參數(shù)傳遞到一個(gè)方法后,此方法可改變這個(gè)對(duì)象的屬性,并可返回變化后的結(jié)果,那么這里到底是值傳遞還是引用傳遞?

              是值傳遞。Java 編程語(yǔ)言只有值傳遞參數(shù)。當(dāng)一個(gè)對(duì)象實(shí)例作為一個(gè)參數(shù)被傳遞到方法中時(shí),參數(shù)的值就是對(duì)該對(duì)象的引用。對(duì)象的內(nèi)容可以在被調(diào)用的方法中改變,但對(duì)象的引用是永遠(yuǎn)不會(huì)改變的。

              5.7  當(dāng)一個(gè)線程進(jìn)入一個(gè)對(duì)象的一個(gè)synchronized方法后,其它線程是否可進(jìn)入此對(duì)象的其它方法?

              不能,一個(gè)對(duì)象的一個(gè)synchronized方法只能由一個(gè)線程訪問。

              (這個(gè)有點(diǎn)疑問:?jiǎn)柕氖沁@個(gè)對(duì)象的其他方法,而非synchonized方法。)

              5.8  編程題: 寫一個(gè)Singleton出來。

              Singleton模式主要作用是保證在Java應(yīng)用程序中,一個(gè)類Class只有一個(gè)實(shí)例存在。

              一般Singleton模式通常有幾種種形式:

              第一種形式: 定義一個(gè)類,它的構(gòu)造函數(shù)為private的,它有一個(gè)static的private的該類變量,在類初始化時(shí)實(shí)例話,通過一個(gè)public的getInstance方法獲取對(duì)它的引用,繼而調(diào)用其中的方法。

          package test;

          public class Singleton {

                   private Singleton() {

                   }

                   // 在自己內(nèi)部定義自己一個(gè)實(shí)例,是不是很奇怪?

                   // 注意這是private 只供內(nèi)部調(diào)用

                   private static Singleton instance = new Singleton();

                   // 這里提供了一個(gè)供外部訪問本class的靜態(tài)方法,可以直接訪問

                   public static Singleton getInstance() {

                             return instance;

                   }

          }


              第二種形式:

          package test;

          public class Singleton {

                   private static Singleton instance = null;

                   public static synchronized Singleton getInstance() {

                             // 這個(gè)方法比上面有所改進(jìn),不用每次都進(jìn)行生成對(duì)象,只是第一次

                             // 使用時(shí)生成實(shí)例,提高了效率!

                             if (instance == null)

                                      instance = new Singleton();

                             return instance;

                   }

          }

              其他形式:

              定義一個(gè)類,它的構(gòu)造函數(shù)為private的,所有方法為static的。

              一般認(rèn)為第一種形式要更加安全

              5.9  Java的接口和C++的虛類的相同和不同處。

              由于Java不支持多繼承,而有可能某個(gè)類或?qū)ο笠褂梅謩e在幾個(gè)類或?qū)ο罄锩娴姆椒ɑ驅(qū)傩裕F(xiàn)有的單繼承機(jī)制就不能滿足要求。與繼承相比,接口有更高的靈活性,因?yàn)榻涌谥袥]有任何實(shí)現(xiàn)代碼。當(dāng)一個(gè)類實(shí)現(xiàn)了接口以后,該類要實(shí)現(xiàn)接口里面所有的方法和屬性,并且接口里面的屬性在默認(rèn)狀態(tài)下面都是public static,所有方法默認(rèn)情況下是public.一個(gè)類可以實(shí)現(xiàn)多個(gè)接口。

              5.10  Java中的異常處理機(jī)制的簡(jiǎn)單原理和應(yīng)用。

              當(dāng)Java程序違反了Java的語(yǔ)義規(guī)則時(shí),Java虛擬機(jī)就會(huì)將發(fā)生的錯(cuò)誤表示為一個(gè)異常。違反語(yǔ)義規(guī)則包括2種情況。一種是Java類庫(kù)內(nèi)置的語(yǔ)義檢查。例如數(shù)組下標(biāo)越界,會(huì)引發(fā)IndexOutOfBoundsException;訪問null的對(duì)象時(shí)會(huì)引發(fā)NullPointerException.另一種情況就是Java允許程序員擴(kuò)展這種語(yǔ)義檢查,程序員可以創(chuàng)建自己的異常,并自由選擇在何時(shí)用throw關(guān)鍵字引發(fā)異常。所有的異常都是java.lang.Thowable的子類。

          posted @ 2010-03-25 21:40 drecry 閱讀(190) | 評(píng)論 (0)編輯 收藏

          JAVA面試題四(轉(zhuǎn))

           4.1  EJB包括(SessionBean,EntityBean)說出他們的生命周期,及如何管理事務(wù)的?

              SessionBean:Stateless Session Bean 的生命周期是由容器決定的,當(dāng)客戶機(jī)發(fā)出請(qǐng)求要建立一個(gè)Bean的實(shí)例時(shí),EJB容器不一定要?jiǎng)?chuàng)建一個(gè)新的Bean的實(shí)例供客戶機(jī)調(diào)用,而是隨便找一個(gè)現(xiàn)有的實(shí)例提供給客戶機(jī)。當(dāng)客戶機(jī)第一次調(diào)用一個(gè)Stateful Session Bean 時(shí),容器必須立即在服務(wù)器中創(chuàng)建一個(gè)新的Bean實(shí)例,并關(guān)聯(lián)到客戶機(jī)上,以后此客戶機(jī)調(diào)用Stateful Session Bean 的方法時(shí)容器會(huì)把調(diào)用分派到與此客戶機(jī)相關(guān)聯(lián)的Bean實(shí)例。

              EntityBean:Entity Beans能存活相對(duì)較長(zhǎng)的時(shí)間,并且狀態(tài)是持續(xù)的。只要數(shù)據(jù)庫(kù)中的數(shù)據(jù)存在,Entity beans就一直存活。而不是按照應(yīng)用程序或者服務(wù)進(jìn)程來說的。即使EJB容器崩潰了,Entity beans也是存活的。Entity Beans生命周期能夠被容器或者 Beans自己管理。

              EJB通過以下技術(shù)管理事務(wù):對(duì)象管理組織(OMG)的對(duì)象事務(wù)服務(wù)(OTS),Sun Microsystems的Transaction Service(JTS)、Java Transaction API(JTA),開發(fā)組(X/Open)的XA接口。

              4.2  應(yīng)用服務(wù)器有那些?

              BEA WebLogic Server,IBM WebSphere Application Server,Oracle9i Application Server,jBoss,Tomcat

              4.3  給我一個(gè)你最常見到的runtime exception.

              ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException.

              4.4  接口是否可繼承接口? 抽象類是否可實(shí)現(xiàn)(implements)接口? 抽象類是否可繼承實(shí)體類(concrete class)?

              接口可以繼承接口。抽象類可以實(shí)現(xiàn)(implements)接口,抽象類是否可繼承實(shí)體類,但前提是實(shí)體類必須有明確的構(gòu)造函數(shù)。

              4.5  List, Set, Map是否繼承自Collection接口?

              List,Set是,Map不是

              4.6  說出數(shù)據(jù)連接池的工作機(jī)制是什么?

              J2EE服務(wù)器啟動(dòng)時(shí)會(huì)建立一定數(shù)量的池連接,并一直維持不少于此數(shù)目的池連接。客戶端程序需要連接時(shí),池驅(qū)動(dòng)程序會(huì)返回一個(gè)未使用的池連接并將其表記為忙。如果當(dāng)前沒有空閑連接,池驅(qū)動(dòng)程序就新建一定數(shù)量的連接,新建連接的數(shù)量有配置參數(shù)決定。當(dāng)使用的池連接調(diào)用完成后,池驅(qū)動(dòng)程序?qū)⒋诉B接表記為空閑,其他調(diào)用就可以使用這個(gè)連接。

              4.7  abstract的method是否可同時(shí)是static,是否可同時(shí)是native,是否可同時(shí)是synchronized?

              都不能

              4.8  數(shù)組有沒有l(wèi)ength()這個(gè)方法? String有沒有l(wèi)ength()這個(gè)方法?

              數(shù)組沒有l(wèi)ength()這個(gè)方法,有l(wèi)ength的屬性。String有有l(wèi)ength()這個(gè)方法。

              4.9  Set里的元素是不能重復(fù)的,那么用什么方法來區(qū)分重復(fù)與否呢? 是用==還是equals()? 它們有何區(qū)別?

              Set里的元素是不能重復(fù)的,那么用iterator()方法來區(qū)分重復(fù)與否。equals()是判讀兩個(gè)Set是否相等。

              equals()和==方法決定引用值是否指向同一對(duì)象equals()在類中被覆蓋,為的是當(dāng)兩個(gè)分離的對(duì)象的內(nèi)容和類型相配的話,返回真值。

              4.10  構(gòu)造器Constructor是否可被override?

              構(gòu)造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading.

          posted @ 2010-03-25 21:39 drecry 閱讀(197) | 評(píng)論 (0)編輯 收藏

          java 面試題三(轉(zhuǎn))

          3.1  Static Nested Class 和 Inner Class的不同。

              Static Nested Class是被聲明為靜態(tài)(static)的內(nèi)部類,它可以不依賴于外部類實(shí)例被實(shí)例化。而通常的內(nèi)部類需要在外部類實(shí)例化后才能實(shí)例化。

              3.2  JSP中動(dòng)態(tài)INCLUDE與靜態(tài)INCLUDE的區(qū)別?

              動(dòng)態(tài)INCLUDE用jsp:include動(dòng)作實(shí)現(xiàn) <jsp:include page="included.jsp" flush="true" />它總是會(huì)檢查所含文件中的變化,適合用于包含動(dòng)態(tài)頁(yè)面,并且可以帶參數(shù)。

              靜態(tài)INCLUDE用include偽碼實(shí)現(xiàn),定不會(huì)檢查所含文件的變化,適用于包含靜態(tài)頁(yè)面<%@ include file="included.htm" %>

              3.3  什么時(shí)候用assert.

              assertion(斷言)在軟件開發(fā)中是一種常用的調(diào)試方式,很多開發(fā)語(yǔ)言中都支持這種機(jī)制。在實(shí)現(xiàn)中,assertion就是在程序中的一條語(yǔ)句,它對(duì)一個(gè)boolean表達(dá)式進(jìn)行檢查,一個(gè)正確程序必須保證這個(gè)boolean表達(dá)式的值為true;如果該值為false,說明程序已經(jīng)處于不正確的狀態(tài)下,系統(tǒng)將給出警告或退出。一般來說,assertion用于保證程序最基本、關(guān)鍵的正確性。assertion檢查通常在開發(fā)和測(cè)試時(shí)開啟。為了提高性能,在軟件發(fā)布后,assertion檢查通常是關(guān)閉的。

              3.4  GC是什么? 為什么要有GC?

              GC是垃圾收集的意思(Gabage Collection),內(nèi)存處理是編程人員容易出現(xiàn)問題的地方,忘記或者錯(cuò)誤的內(nèi)存回收會(huì)導(dǎo)致程序或系統(tǒng)的不穩(wěn)定甚至崩潰,Java提供的GC功能可以自動(dòng)監(jiān)測(cè)對(duì)象是否超過作用域從而達(dá)到自動(dòng)回收內(nèi)存的目的,Java語(yǔ)言沒有提供釋放已分配內(nèi)存的顯示操作方法。

              3.5  short s1 = 1; s1 = s1 + 1;有什么錯(cuò)? short s1 = 1; s1 += 1;有什么錯(cuò)?

              short s1 = 1; s1 = s1 + 1; (s1+1運(yùn)算結(jié)果是int型,需要強(qiáng)制轉(zhuǎn)換類型)

              short s1 = 1; s1 += 1;(可以正確編譯)

              3.6  Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

              Math.round(11.5)==12

              Math.round(-11.5)==-11

              round方法返回與參數(shù)最接近的長(zhǎng)整數(shù),參數(shù)加1/2后求其floor.

              3.7  String s = new String("xyz");創(chuàng)建了幾個(gè)String Object?

              兩個(gè)

              3.8  設(shè)計(jì)4個(gè)線程,其中兩個(gè)線程每次對(duì)j增加1,另外兩個(gè)線程對(duì)j每次減少1.寫出程序。

              以下程序使用內(nèi)部類實(shí)現(xiàn)線程,對(duì)j增減的時(shí)候沒有考慮順序問題。

          package test;

          public class ThreadTest1 {

                   private int j;

                   public static void main(String args[]) {

                             ThreadTest1 tt = new ThreadTest1();

                             Inc inc = tt.new Inc();

                             Dec dec = tt.new Dec();

                             for (int i = 0; i < 2; i++) {

                                      Thread t = new Thread(inc);

                                      t.start();

                                      t = new Thread(dec);

                                      t.start();

                             }

                   }

                   private synchronized void inc() {

                             j++;

                             System.out.println(Thread.currentThread().getName() + "-inc:" + j);

                   }

                   private synchronized void dec() {

                             j--;

                             System.out.println(Thread.currentThread().getName() + "-dec:" + j);

                   }

                   class Inc implements Runnable {

                             public void run() {

                                      for (int i = 0; i < 3; i++) {

                                               inc();

                                      }

                             }

                   }

                   class Dec implements Runnable {

                             public void run() {

                                      for (int i = 0; i < 3; i++) {

                                               dec();

                                      }

                             }

                   }

          }

              3.9  Java有沒有g(shù)oto?

              Java中的保留字,現(xiàn)在沒有在Java中使用。

              3.10  啟動(dòng)一個(gè)線程是用run()還是start()?

              啟動(dòng)一個(gè)線程是調(diào)用start()方法,使線程所代表的虛擬處理機(jī)處于可運(yùn)行狀態(tài),這意味著它可以由JVM調(diào)度并執(zhí)行。這并不意味著線程就會(huì)立即運(yùn)行。run()方法可以產(chǎn)生必須退出的標(biāo)志來停止一個(gè)線程。

          posted @ 2010-03-25 21:38 drecry 閱讀(177) | 評(píng)論 (0)編輯 收藏

          java 面試題二(轉(zhuǎn))

            2.1  HashMap和Hashtable的區(qū)別。

              HashMap是Hashtable的輕量級(jí)實(shí)現(xiàn)(非線程安全的實(shí)現(xiàn)),他們都完成了Map接口,主要區(qū)別在于HashMap允許空(null)鍵值(key),由于非線程安全,效率上可能高于Hashtable.

              HashMap允許將null作為一個(gè)entry的key或者value,而Hashtable不允許。

              HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey.因?yàn)閏ontains方法容易讓人引起誤解。

              Hashtable繼承自Dictionary類,而HashMap是Java1.2引進(jìn)的Map interface的一個(gè)實(shí)現(xiàn)。

              最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個(gè)線程訪問Hashtable時(shí),不需要自己為它的方法實(shí)現(xiàn)同步,而HashMap 就必須為之提供外同步。Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會(huì)有很大的差異。

              2.2  final, finally, finalize的區(qū)別。

              final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。

              finally是異常處理語(yǔ)句結(jié)構(gòu)的一部分,表示總是執(zhí)行。

              finalize是Object類的一個(gè)方法,在垃圾收集器執(zhí)行的時(shí)候會(huì)調(diào)用被回收對(duì)象的此方法,可以覆蓋此方法提供垃圾收集時(shí)的其他資源回收,例如關(guān)閉文件等。

              2.3  sleep() 和 wait() 有什么區(qū)別?

              sleep是線程類(Thread)的方法,導(dǎo)致此線程暫停執(zhí)行指定時(shí)間,給執(zhí)行機(jī)會(huì)給其他線程,但是監(jiān)控狀態(tài)依然保持,到時(shí)后會(huì)自動(dòng)恢復(fù)。調(diào)用sleep不會(huì)釋放對(duì)象鎖。

              wait是Object類的方法,對(duì)此對(duì)象調(diào)用wait方法導(dǎo)致本線程放棄對(duì)象鎖,進(jìn)入等待此對(duì)象的等待鎖定池,只有針對(duì)此對(duì)象發(fā)出notify方法(或notifyAll)后本線程才進(jìn)入對(duì)象鎖定池準(zhǔn)備獲得對(duì)象鎖進(jìn)入運(yùn)行狀態(tài)。

              2.4  Overload和Override的區(qū)別。Overloaded的方法是否可以改變返回值的類型?

              方法的重寫Overriding和重載Overloading是Java多態(tài)性的不同表現(xiàn)。重寫Overriding是父類與子類之間多態(tài)性的一種表現(xiàn),重載Overloading是一個(gè)類中多態(tài)性的一種表現(xiàn)。如果在子類中定義某方法與其父類有相同的名稱和參數(shù),我們說該方法被重寫 (Overriding)。子類的對(duì)象使用這個(gè)方法時(shí),將調(diào)用子類中的定義,對(duì)它而言,父類中的定義如同被"屏蔽"了。如果在一個(gè)類中定義了多個(gè)同名的方法,它們或有不同的參數(shù)個(gè)數(shù)或有不同的參數(shù)類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。

              2.5  error和exception有什么區(qū)別?

              error 表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問題。比如說內(nèi)存溢出。不可能指望程序能處理這樣的情況。

              exception 表示一種設(shè)計(jì)或?qū)崿F(xiàn)問題。也就是說,它表示如果程序運(yùn)行正常,從不會(huì)發(fā)生的情況。

              2.6  同步和異步有何異同,在什么情況下分別使用他們?舉例說明。

              如果數(shù)據(jù)將在線程間共享。例如正在寫的數(shù)據(jù)以后可能被另一個(gè)線程讀到,或者正在讀的數(shù)據(jù)可能已經(jīng)被另一個(gè)線程寫過了,那么這些數(shù)據(jù)就是共享數(shù)據(jù),必須進(jìn)行同步存取。

              當(dāng)應(yīng)用程序在對(duì)象上調(diào)用了一個(gè)需要花費(fèi)很長(zhǎng)時(shí)間來執(zhí)行的方法,并且不希望讓程序等待方法的返回時(shí),就應(yīng)該使用異步編程,在很多情況下采用異步途徑往往更有效率。

              2.7  abstract class和interface有什么區(qū)別?

              聲明方法的存在而不去實(shí)現(xiàn)它的類被叫做抽象類(abstract class),它用于要?jiǎng)?chuàng)建一個(gè)體現(xiàn)某些基本行為的類,并為該類聲明方法,但不能在該類中實(shí)現(xiàn)該類的情況。不能創(chuàng)建abstract 類的實(shí)例。然而可以創(chuàng)建一個(gè)變量,其類型是一個(gè)抽象類,并讓它指向具體子類的一個(gè)實(shí)例。不能有抽象構(gòu)造函數(shù)或抽象靜態(tài)方法。Abstract 類的子類為它們父類中的所有抽象方法提供實(shí)現(xiàn),否則它們也是抽象類為。取而代之,在子類中實(shí)現(xiàn)該方法。知道其行為的其它類可以在類中實(shí)現(xiàn)這些方法。

              接口(interface)是抽象類的變體。在接口中,所有方法都是抽象的。多繼承性可通過實(shí)現(xiàn)這樣的接口而獲得。接口中的所有方法都是抽象的,沒有一個(gè)有程序體。接口只可以定義static final成員變量。接口的實(shí)現(xiàn)與子類相似,除了該實(shí)現(xiàn)類不能從接口定義中繼承行為。當(dāng)類實(shí)現(xiàn)特殊接口時(shí),它定義(即將程序體給予)所有這種接口的方法。然后,它可以在實(shí)現(xiàn)了該接口的類的任何對(duì)象上調(diào)用接口的方法。由于有抽象類,它允許使用接口名作為引用變量的類型。通常的動(dòng)態(tài)聯(lián)編將生效。引用可以轉(zhuǎn)換到接口類型或從接口類型轉(zhuǎn)換,instanceof 運(yùn)算符可以用來決定某對(duì)象的類是否實(shí)現(xiàn)了接口。

              2.8  heap和stack有什么區(qū)別。

              棧是一種線形集合,其添加和刪除元素的操作應(yīng)在同一段完成。棧按照后進(jìn)先出的方式進(jìn)行處理。

              堆是棧的一個(gè)組成元素。

              2.9  forward 和redirect的區(qū)別

              forward是服務(wù)器請(qǐng)求資源,服務(wù)器直接訪問目標(biāo)地址的URL,把那個(gè)URL的響應(yīng)內(nèi)容讀取過來,然后把這些內(nèi)容再發(fā)給瀏覽器,瀏覽器根本不知道服務(wù)器發(fā)送的內(nèi)容是從哪兒來的,所以它的地址欄中還是原來的地址。

              redirect就是服務(wù)端根據(jù)邏輯,發(fā)送一個(gè)狀態(tài)碼,告訴瀏覽器重新去請(qǐng)求那個(gè)地址,一般來說瀏覽器會(huì)用剛才請(qǐng)求的所有參數(shù)重新請(qǐng)求,所以session,request參數(shù)都可以獲取。

              2.10  EJB與Java Bean的區(qū)別?

              Java Bean 是可復(fù)用的組件,對(duì)Java Bean并沒有嚴(yán)格的規(guī)范,理論上講,任何一個(gè)Java類都可以是一個(gè)Bean.但通常情況下,由于Java Bean是被容器所創(chuàng)建(如Tomcat)的,所以Java Bean應(yīng)具有一個(gè)無參的構(gòu)造器,另外,通常Java Bean還要實(shí)現(xiàn)Serializable接口用于實(shí)現(xiàn)Bean的持久性。Java Bean實(shí)際上相當(dāng)于微軟COM模型中的本地進(jìn)程內(nèi)COM組件,它是不能被跨進(jìn)程訪問的。Enterprise Java Bean 相當(dāng)于DCOM,即分布式組件。它是基于Java的遠(yuǎn)程方法調(diào)用(RMI)技術(shù)的,所以EJB可以被遠(yuǎn)程訪問(跨進(jìn)程、跨計(jì)算機(jī))。但EJB必須被布署在諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問真正的EJB組件,而是通過其容器訪問。EJB容器是EJB組件的代理,EJB組件由容器所創(chuàng)建和管理。客戶通過容器來訪問真正的EJB組件。

          posted @ 2010-03-25 21:37 drecry 閱讀(199) | 評(píng)論 (0)編輯 收藏

          java 面試題一(轉(zhuǎn))

           一、面向?qū)ο蟮奶卣饔心男┓矫?

              1.抽象:

              抽象就是忽略一個(gè)主題中與當(dāng)前目標(biāo)無關(guān)的那些方面,以便更充分地注意與當(dāng)前目標(biāo)有關(guān)的方面。抽象并不打算了解全部問題,而只是選擇其中的一部分,暫時(shí)不用部分細(xì)節(jié)。抽象包括兩個(gè)方面,一是過程抽象,二是數(shù)據(jù)抽象。

              2.繼承:

              繼承是一種聯(lián)結(jié)類的層次模型,并且允許和鼓勵(lì)類的重用,它提供了一種明確表述共性的方法。對(duì)象的一個(gè)新類可以從現(xiàn)有的類中派生,這個(gè)過程稱為類繼承。新類繼承了原始類的特性,新類稱為原始類的派生類(子類),而原始類稱為新類的基類(父類)。派生類可以從它的基類那里繼承方法和實(shí)例變量,并且類可以修改或增加新的方法使之更適合特殊的需要。

              3.封裝:

              封裝是把過程和數(shù)據(jù)包圍起來,對(duì)數(shù)據(jù)的訪問只能通過已定義的界面。面向?qū)ο笥?jì)算始于這個(gè)基本概念,即現(xiàn)實(shí)世界可以被描繪成一系列完全自治、封裝的對(duì)象,這些對(duì)象通過一個(gè)受保護(hù)的接口訪問其他對(duì)象。

              4.多態(tài)性:

              多態(tài)性是指允許不同類的對(duì)象對(duì)同一消息作出響應(yīng)。多態(tài)性包括參數(shù)化多態(tài)性和包含多態(tài)性。多態(tài)性語(yǔ)言具有靈活、抽象、行為共享、代碼共享的優(yōu)勢(shì),很好的解決了應(yīng)用程序函數(shù)同名問題。

              二、String是最基本的數(shù)據(jù)類型嗎?

              基本數(shù)據(jù)類型包括byte、int、char、long、float、double、boolean和short.  java.lang.String類是final類型的,因此不可以繼承這個(gè)類、不能修改這個(gè)類。為了提高效率節(jié)省空間,我們應(yīng)該用StringBuffer類。

              三、int 和 Integer 有什么區(qū)別?

              Java 提供兩種不同的類型:引用類型和原始類型(或內(nèi)置類型)。int是Java的原始數(shù)據(jù)類型,Integer是Java為int提供的封裝類。Java為每個(gè)原始類型提供了封裝類。

              原始類型封裝類

              boolean Boolean

              char Character

              byte Byte

              short Short

              int Integer

              long Long

              float Float

              double Double

              引用類型和原始類型的行為完全不同,并且它們具有不同的語(yǔ)義。引用類型和原始類型具有不同的特征和用法,它們包括:大小和速度問題,這種類型以哪種類型的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ),當(dāng)引用類型和原始類型用作某個(gè)類的實(shí)例數(shù)據(jù)時(shí)所指定的缺省值。對(duì)象引用實(shí)例變量的缺省值為 null,而原始類型實(shí)例變量的缺省值與它們的類型有關(guān)。

              四、String 和StringBuffer的區(qū)別?

              Java平臺(tái)提供了兩個(gè)類:String和StringBuffer,它們可以儲(chǔ)存和操作字符串,即包含多個(gè)字符的字符數(shù)據(jù)。這個(gè)String類提供了數(shù)值不可改變的字符串。而這個(gè)StringBuffer類提供的字符串進(jìn)行修改。當(dāng)你知道字符數(shù)據(jù)要改變的時(shí)候你就可以使用StringBuffer.典型地,你可以使用StringBuffer來動(dòng)態(tài)構(gòu)造字符數(shù)據(jù)。

              五、運(yùn)行時(shí)異常與一般異常有何異同?

              異常表示程序運(yùn)行過程中可能出現(xiàn)的非正常狀態(tài),運(yùn)行時(shí)異常表示虛擬機(jī)的通常操作中可能遇到的異常,是一種常見運(yùn)行錯(cuò)誤。Java編譯器要求方法必須聲明拋出可能發(fā)生的非運(yùn)行時(shí)異常,但是并不要求必須聲明拋出未被捕獲的運(yùn)行時(shí)異常。

               六、說出Servlet的生命周期,并說出Servlet和CGI的區(qū)別。

              Servlet被服務(wù)器實(shí)例化后,容器運(yùn)行其init方法,請(qǐng)求到達(dá)時(shí)運(yùn)行其service方法,service方法自動(dòng)派遣運(yùn)行與請(qǐng)求對(duì)應(yīng)的doXXX方法(doGet,doPost)等,當(dāng)服務(wù)器決定將實(shí)例銷毀的時(shí)候調(diào)用其destroy方法。

              與CGI的區(qū)別在于Servlet處于服務(wù)器進(jìn)程中,它通過多線程方式運(yùn)行其service方法,一個(gè)實(shí)例可以服務(wù)于多個(gè)請(qǐng)求,并且其實(shí)例一般不會(huì)銷毀,而CGI對(duì)每個(gè)請(qǐng)求都產(chǎn)生新的進(jìn)程,服務(wù)完成后就銷毀,所以效率上低于CGI.

              七、說出ArrayList,Vector, LinkedList的存儲(chǔ)性能和特性

              ArrayList和Vector都是使用數(shù)組方式存儲(chǔ)數(shù)據(jù),此數(shù)組元素?cái)?shù)大于實(shí)際存儲(chǔ)的數(shù)據(jù)以便增加和插入元素,它們都允許直接按序號(hào)索引元素,但是插入元素要涉及數(shù)組元素移動(dòng)等內(nèi)存操作,所以索引數(shù)據(jù)快而插入數(shù)據(jù)慢,Vector由于使用了synchronized方法(線程安全),通常性能上較ArrayList差,而LinkedList使用雙向鏈表實(shí)現(xiàn)存儲(chǔ),按序號(hào)索引數(shù)據(jù)需要進(jìn)行前向或后向遍歷,但是插入數(shù)據(jù)時(shí)只需要記錄本項(xiàng)的前后項(xiàng)即可,所以插入速度較快。

              八、EJB是基于哪些技術(shù)實(shí)現(xiàn)的?并說出SessionBean和EntityBean的區(qū)別,StatefulBean和StatelessBean的區(qū)別。

              EJB包括Session Bean、Entity Bean、Message Driven Bean,基于JNDI、RMI、JAT等技術(shù)實(shí)現(xiàn)。

              SessionBean在J2EE應(yīng)用程序中被用來完成一些服務(wù)器端的業(yè)務(wù)操作,例如訪問數(shù)據(jù)庫(kù)、調(diào)用其他EJB組件。EntityBean被用來代表應(yīng)用系統(tǒng)中用到的數(shù)據(jù)。

              對(duì)于客戶機(jī),SessionBean是一種非持久性對(duì)象,它實(shí)現(xiàn)某些在服務(wù)器上運(yùn)行的業(yè)務(wù)邏輯。

              對(duì)于客戶機(jī),EntityBean是一種持久性對(duì)象,它代表一個(gè)存儲(chǔ)在持久性存儲(chǔ)器中的實(shí)體的對(duì)象視圖,或是一個(gè)由現(xiàn)有企業(yè)應(yīng)用程序?qū)崿F(xiàn)的實(shí)體。

              Session Bean 還可以再細(xì)分為 Stateful Session Bean 與 Stateless Session Bean ,這兩種的 Session Bean都可以將系統(tǒng)邏輯放在 method之中執(zhí)行,不同的是 Stateful Session Bean 可以記錄呼叫者的狀態(tài),因此通常來說,一個(gè)使用者會(huì)有一個(gè)相對(duì)應(yīng)的 Stateful Session Bean 的實(shí)體。Stateless Session Bean 雖然也是邏輯組件,但是他卻不負(fù)責(zé)記錄使用者狀態(tài),也就是說當(dāng)使用者呼叫 Stateless Session Bean 的時(shí)候,EJB Container 并不會(huì)找尋特定的 Stateless Session Bean 的實(shí)體來執(zhí)行這個(gè) method.換言之,很可能數(shù)個(gè)使用者在執(zhí)行某個(gè) Stateless Session Bean 的 methods 時(shí),會(huì)是同一個(gè) Bean 的 Instance 在執(zhí)行。從內(nèi)存方面來看, Stateful Session Bean 與 Stateless Session Bean 比較, Stateful Session Bean 會(huì)消耗 J2EE Server 較多的內(nèi)存,然而 Stateful Session Bean 的優(yōu)勢(shì)卻在于他可以維持使用者的狀態(tài)。

              九、Collection 和 Collections的區(qū)別。

              Collection是集合類的上級(jí)接口,繼承與他的接口主要有Set 和List.

              Collections是針對(duì)集合類的一個(gè)幫助類,他提供一系列靜態(tài)方法實(shí)現(xiàn)對(duì)各種集合的搜索、排序、線程安全化等操作。

              十、&和&&的區(qū)別。

              &是位運(yùn)算符,表示按位與運(yùn)算,&&是邏輯運(yùn)算符,表示邏輯與(and)。

          posted @ 2010-03-25 21:35 drecry 閱讀(189) | 評(píng)論 (0)編輯 收藏

          JVM,JRE,JDK到底是個(gè)什么樣的關(guān)系(轉(zhuǎn))

          JVM JRE JDK,這些東西到底是什么?

            我們?cè)诎惭b好JDK后就可以想象成我們已經(jīng)買了一臺(tái)安裝好軟件的新的電腦。

            JVM : Java Virtual Machine(Java虛擬機(jī)) 。所謂“虛擬機(jī)”顧名思義就是模擬出來的東西。就像是我們?cè)谟秒娔X看電視,但是電腦里并沒有像電視機(jī)里面一樣的硬件支持,但是我們?nèi)匀豢梢詮碾娔X里接受電視臺(tái)的節(jié)目。那是因?yàn)槲覀兙帉懥艘粋€(gè)可以模擬電視機(jī)硬件工作的軟件運(yùn)行在電腦的平臺(tái)上面的原因。同樣JVM就是模擬了電腦的硬件,它同樣有著像CPU一樣可以執(zhí)行代碼的功能。它的實(shí)現(xiàn)具體有:指令集 寄存器組 類文件格式 棧 垃圾收集堆 內(nèi)存區(qū)。可以把它理解成是專門用來執(zhí)行Java程序的一臺(tái)機(jī)器。也就是說JVM提供了Java執(zhí)行的硬件平臺(tái)。JVM上執(zhí)行的代碼都存放在 .CLASS 文件中。JVM只執(zhí)行字節(jié)碼文件。

            JRE : Java Runtime Environment(Java運(yùn)行環(huán)境)。就是可以運(yùn)行Java程序的地方。就像是我們要在電腦上運(yùn)行一個(gè)視頻軟件的時(shí)候必須在Windos或者是Linux等操作系統(tǒng)上一樣。那我們就可以把它看做是一個(gè)操作系統(tǒng)。也就是說JRE提供了Java執(zhí)行的軟件平臺(tái)。在運(yùn)行Java的過程中除了需要有JVM執(zhí)行Java代碼這個(gè)動(dòng)作外,還需要Java API(Application Programming Interface,應(yīng)用編程接口)說簡(jiǎn)單的就是“類庫(kù)”。Java程序在運(yùn)行中沒有這些API是不行的,所以JRE包含JVM。

            JDK : Java Development ToolKit(Java開發(fā)工具包)。我們有了硬件和軟件兩個(gè)平臺(tái)后就可以做我們自己想做的事情了。JDK就是我們用來做事情的工具,它包括JRE還有其他工具。我們所說版本的不同,也就是說它里面的工具有差異。就像是你不同的工具箱里放著不同的工具一樣。舉個(gè)例子:最常用的一個(gè)就是javac,它是把.java的文件翻譯成.class文件的工具。然后讓JVM來執(zhí)行.class文件中的字節(jié)碼。(就像電腦的CPU只認(rèn)識(shí)0或1的道理)

            如果一臺(tái)計(jì)算機(jī)的需求只是運(yùn)行Java程序,而不是去編寫Java程序的時(shí)候,它只需要安裝JRE就可以了。現(xiàn)在大家知道JVM JRE JDK,這些東西到底是什么了吧。

          posted @ 2010-03-25 21:13 drecry 閱讀(327) | 評(píng)論 (0)編輯 收藏

          2010年3月20日 #

          java 異常處理(轉(zhuǎn))

              摘要:本文從Java異常最基本的概念、語(yǔ)法開始講述了Java異常處理的基本知識(shí),分析了Java異常體系結(jié)構(gòu),對(duì)比Spring的異常處理框架,闡述了異常處理的基本原則。并且作者提出了自己處理一個(gè)大型應(yīng)用系統(tǒng)異常的思想,并通過設(shè)計(jì)一個(gè)異常處理的框架來論述此思想。

               一、 異常的概念和Java異常體系結(jié)構(gòu)

              異常是程序運(yùn)行過程中出現(xiàn)的錯(cuò)誤。本文主要講授的是Java語(yǔ)言的異常處理。Java語(yǔ)言的異常處理框架,是Java語(yǔ)言健壯性的一個(gè)重要體現(xiàn)。

              Java把異常當(dāng)作對(duì)象來處理,并定義一個(gè)基類java.lang.Throwable作為所有異常的超類。在Java API中已經(jīng)定義了許多異常類,這些異常類分為兩大類,錯(cuò)誤Error和異常Exception。Java異常體系結(jié)構(gòu)呈樹狀,其層次結(jié)構(gòu)圖如圖 1所示:

           


           Thorwable類所有異常和錯(cuò)誤的超類,有兩個(gè)子類Error和Exception,分別表示錯(cuò)誤和異常。其中異常類Exception又分為運(yùn)行時(shí)異常(RuntimeException)和非運(yùn)行時(shí)異常,這兩種異常有很大的區(qū)別,也稱之為不檢查異常(Unchecked Exception)和檢查異常(Checked Exception)。下面將詳細(xì)講述這些異常之間的區(qū)別與聯(lián)系:

              1、Error與Exception

              Error是程序無法處理的錯(cuò)誤,比如OutOfMemoryError、ThreadDeath等。這些異常發(fā)生時(shí),Java虛擬機(jī)(JVM)一般會(huì)選擇線程終止。

              Exception是程序本身可以處理的異常,這種異常分兩大類運(yùn)行時(shí)異常和非運(yùn)行時(shí)異常。程序中應(yīng)當(dāng)盡可能去處理這些異常。

              2、運(yùn)行時(shí)異常和非運(yùn)行時(shí)異常

              運(yùn)行時(shí)異常都是RuntimeException類及其子類異常,如NullPointerException、IndexOutOfBoundsException等,這些異常是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。這些異常一般是由程序邏輯錯(cuò)誤引起的,程序應(yīng)該從邏輯角度盡可能避免這類異常的發(fā)生。

              非運(yùn)行時(shí)異常是RuntimeException以外的異常,類型上都屬于Exception類及其子類。從程序語(yǔ)法角度講是必須進(jìn)行處理的異常,如果不處理,程序就不能編譯通過。如IOException、SQLException等以及用戶自定義的Exception異常,一般情況下不自定義檢查異常。
           二、 異常的捕獲和處理

              Java異常的捕獲和處理是一個(gè)不容易把握的事情,如果處理不當(dāng),不但會(huì)讓程序代碼的可讀性大大降低,而且導(dǎo)致系統(tǒng)性能低下,甚至引發(fā)一些難以發(fā)現(xiàn)的錯(cuò)誤。

              Java異常處理涉及到五個(gè)關(guān)鍵字,分別是:try、catch、finally、throw、throws。下面將驟一介紹,通過認(rèn)識(shí)這五個(gè)關(guān)鍵字,掌握基本異常處理知識(shí)。

              1、 異常處理的基本語(yǔ)法
              在java中,異常處理的完整語(yǔ)法是:
             
           try{
                //(嘗試運(yùn)行的)程序代碼
              }catch(異常類型 異常的變量名){
                //異常處理代碼
              }finally{
                //異常發(fā)生,方法返回之前,總是要執(zhí)行的代碼
              }

              以上語(yǔ)法有三個(gè)代碼塊:
              try語(yǔ)句塊,表示要嘗試運(yùn)行代碼,try語(yǔ)句塊中代碼受異常監(jiān)控,其中代碼發(fā)生異常時(shí),會(huì)拋出異常對(duì)象。

              catch語(yǔ)句塊會(huì)捕獲try代碼塊中發(fā)生的異常并在其代碼塊中做異常處理,catch語(yǔ)句帶一個(gè)Throwable類型的參數(shù),表示可捕獲異常類型。當(dāng)try中出現(xiàn)異常時(shí),catch會(huì)捕獲到發(fā)生的異常,并和自己的異常類型匹配,若匹配,則執(zhí)行catch塊中代碼,并將catch塊參數(shù)指向所拋的異常對(duì)象。catch語(yǔ)句可以有多個(gè),用來匹配多個(gè)中的一個(gè)異常,一旦匹配上后,就不再嘗試匹配別的catch塊了。通過異常對(duì)象可以獲取異常發(fā)生時(shí)完整的JVM堆棧信息,以及異常信息和異常發(fā)生的原因等。

              finally語(yǔ)句塊是緊跟catch語(yǔ)句后的語(yǔ)句塊,這個(gè)語(yǔ)句塊總是會(huì)在方法返回前執(zhí)行,而不管是否try語(yǔ)句塊是否發(fā)生異常。并且這個(gè)語(yǔ)句塊總是在方法返回前執(zhí)行。目的是給程序一個(gè)補(bǔ)救的機(jī)會(huì)。這樣做也體現(xiàn)了Java語(yǔ)言的健壯性。

              2、 try、catch、finally三個(gè)語(yǔ)句塊應(yīng)注意的問題
              第一、try、catch、finally三個(gè)語(yǔ)句塊均不能單獨(dú)使用,三者可以組成 try...catch...finally、try...catch、try...finally三種結(jié)構(gòu),catch語(yǔ)句可以有一個(gè)或多個(gè),finally語(yǔ)句最多一個(gè)。
              第二、try、catch、finally三個(gè)代碼塊中變量的作用域?yàn)榇a塊內(nèi)部,分別獨(dú)立而不能相互訪問。如果要在三個(gè)塊中都可以訪問,則需要將變量定義到這些塊的外面。
              第三、多個(gè)catch塊時(shí)候,只會(huì)匹配其中一個(gè)異常類并執(zhí)行catch塊代碼,而不會(huì)再執(zhí)行別的catch塊,并且匹配catch語(yǔ)句的順序是由上到下。

              3、throw、throws關(guān)鍵字
              throw關(guān)鍵字是用于方法體內(nèi)部,用來拋出一個(gè)Throwable類型的異常。如果拋出了檢查異常,則還應(yīng)該在方法頭部聲明方法可能拋出的異常類型。該方法的調(diào)用者也必須檢查處理拋出的異常。如果所有方法都層層上拋獲取的異常,最終JVM會(huì)進(jìn)行處理,處理也很簡(jiǎn)單,就是打印異常消息和堆棧信息。如果拋出的是Error或RuntimeException,則該方法的調(diào)用者可選擇處理該異常。有關(guān)異常的轉(zhuǎn)譯會(huì)在下面說明。

              throws關(guān)鍵字用于方法體外部的方法聲明部分,用來聲明方法可能會(huì)拋出某些異常。僅當(dāng)拋出了檢查異常,該方法的調(diào)用者才必須處理或者重新拋出該異常。當(dāng)方法的調(diào)用者無力處理該異常的時(shí)候,應(yīng)該繼續(xù)拋出,而不是囫圇吞棗一般在catch塊中打印一下堆棧信息做個(gè)勉強(qiáng)處理。下面給出一個(gè)簡(jiǎn)單例子,看看如何使用這兩個(gè)關(guān)鍵字:
                 
           public static void test3() throws Exception{
                //拋出一個(gè)檢查異常
                      throw new Exception("方法test3中的Exception");
                  }

              3、 Throwable類中的常用方法
              getCause():返回拋出異常的原因。如果 cause 不存在或未知,則返回 null。
              getMessage():返回異常的消息信息。
              printStackTrace():對(duì)象的堆棧跟蹤輸出至錯(cuò)誤輸出流,作為字段 System.err 的值。


           三、 異常處理的一般原則

              1、 能處理就早處理,拋出不去還不能處理的就想法消化掉或者轉(zhuǎn)換為RuntimeException處理。因?yàn)閷?duì)于一個(gè)應(yīng)用系統(tǒng)來說,拋出大量異常是有問題的,應(yīng)該從程序開發(fā)角度盡可能的控制異常發(fā)生的可能。
              2、 對(duì)于檢查異常,如果不能行之有效的處理,還不如轉(zhuǎn)換為RuntimeException拋出。這樣也讓上層的代碼有選擇的余地――可處理也可不處理。
              3、 對(duì)于一個(gè)應(yīng)用系統(tǒng)來說,應(yīng)該有自己的一套異常處理框架,這樣當(dāng)異常發(fā)生時(shí),也能得到統(tǒng)一的處理風(fēng)格,將優(yōu)雅的異常信息反饋給用戶。

              四、 異常的轉(zhuǎn)譯與異常鏈

              1、異常轉(zhuǎn)譯的原理

              所謂的異常轉(zhuǎn)譯就是將一種異常轉(zhuǎn)換另一種新的異常,也許這種新的異常更能準(zhǔn)確表達(dá)程序發(fā)生異常。

              在Java中有個(gè)概念就是異常原因,異常原因?qū)е庐?dāng)前拋出異常的那個(gè)異常對(duì)象,幾乎所有帶異常原因的異常構(gòu)造方法都使用Throwable類型做參數(shù),這也就為異常的轉(zhuǎn)譯提供了直接的支持,因?yàn)槿魏涡问降漠惓:湾e(cuò)誤都是Throwable的子類。比如將SQLException轉(zhuǎn)換為另外一個(gè)新的異常DAOException,可以這么寫:

              先自定義一個(gè)異常DAOException:

              
           public class DAOException extends RuntimeException {
               //(省略了部分代碼)
                  public DAOException(String message, Throwable cause) {
                      super(message, cause);
                  }
              }
              比如有一個(gè)SQLException類型的異常對(duì)象e,要轉(zhuǎn)換為DAOException,可以這么寫:

              DAOException daoEx = new DAOException ( "SQL異常", e);

              異常轉(zhuǎn)譯是針對(duì)所有繼承Throwable超類的類而言的,從編程的語(yǔ)法角度講,其子類之間都可以相互轉(zhuǎn)換。但是,從合理性和系統(tǒng)設(shè)計(jì)角度考慮,可將異常分為三類:Error、Exception、RuntimeException,筆者認(rèn)為,合理的轉(zhuǎn)譯關(guān)系圖應(yīng)該如圖 2:

             

          2 異常轉(zhuǎn)譯

              為什么要這么做呢?筆者認(rèn)為,異常的處理存在著一套哲學(xué)思想:對(duì)于一個(gè)應(yīng)用系統(tǒng)來說,系統(tǒng)所發(fā)生的任何異常或者錯(cuò)誤對(duì)操作用戶來說都是系統(tǒng)"運(yùn)行時(shí)"異常,都是這個(gè)應(yīng)用系統(tǒng)內(nèi)部的異常。這也是異常轉(zhuǎn)譯和應(yīng)用系統(tǒng)異常框架設(shè)計(jì)的指導(dǎo)原則。在系統(tǒng)中大量處理非檢查異常的負(fù)面影響很多,最重要的一個(gè)方面就是代碼可讀性降低,程序編寫復(fù)雜,異常處理的代碼也很蒼白無力。因此,很有必要將這些檢查異常Exception和錯(cuò)誤Error轉(zhuǎn)換為RuntimeException異常,讓程序員根據(jù)情況來決定是否捕獲和處理所發(fā)生的異常。

              圖中的三條線標(biāo)識(shí)轉(zhuǎn)換的方向,分三種情況:

              ①:Error到Exception:將錯(cuò)誤轉(zhuǎn)換為異常,并繼續(xù)拋出。例如Spring WEB框架中,將org.springframework.web.servlet.DispatcherServlet的doDispatch()方法中,將捕獲的錯(cuò)誤轉(zhuǎn)譯為一個(gè)NestedServletException異常。這樣做的目的是為了最大限度挽回因錯(cuò)誤發(fā)生帶來的負(fù)面影響。因?yàn)橐粋€(gè)Error常常是很嚴(yán)重的錯(cuò)誤,可能會(huì)引起系統(tǒng)掛起。

              ②:Exception到RuntimeException:將檢查異常轉(zhuǎn)換為RuntimeException可以讓程序代碼變得更優(yōu)雅,讓開發(fā)人員集中經(jīng)理設(shè)計(jì)更合理的程序代碼,反過來也增加了系統(tǒng)發(fā)生異常的可能性。

              ③:Error到RuntimeException:目的還是一樣的。把所有的異常和錯(cuò)誤轉(zhuǎn)譯為不檢查異常,這樣可以讓代碼更為簡(jiǎn)潔,還有利于對(duì)錯(cuò)誤和異常信息的統(tǒng)一處理。

              1、 異常鏈

              異常鏈顧名思義就是將異常發(fā)生的原因一個(gè)傳一個(gè)串起來,即把底層的異常信息傳給上層,這樣逐層拋出。Java API文檔中給出了一個(gè)簡(jiǎn)單的模型:

             
           try {
               lowLevelOp();
              } catch (LowLevelException le) {
               throw (HighLevelException)
                new HighLevelException().initCause(le);
              }

              當(dāng)程序捕獲到了一個(gè)底層異常le,在處理部分選擇了繼續(xù)拋出一個(gè)更高級(jí)別的新異常給此方法的調(diào)用者。這樣異常的原因就會(huì)逐層傳遞。這樣,位于高層的異常遞歸調(diào)用getCause()方法,就可以遍歷各層的異常原因。這就是Java異常鏈的原理。異常鏈的實(shí)際應(yīng)用很少,發(fā)生異常時(shí)候逐層上拋不是個(gè)好注意,上層拿到這些異常又能奈之何?而且異常逐層上拋會(huì)消耗大量資源,因?yàn)橐4嬉粋€(gè)完整的異常鏈信息


            五、 設(shè)計(jì)一個(gè)高效合理的異常處理框架

              對(duì)于一個(gè)應(yīng)用系統(tǒng)來說,發(fā)生所有異常在用戶看來都是應(yīng)用系統(tǒng)內(nèi)部的異常。因此應(yīng)該設(shè)計(jì)一套應(yīng)用系統(tǒng)的異常框架,以處理系統(tǒng)運(yùn)行過程中的所有異常。

              基于這種觀點(diǎn),可以設(shè)計(jì)一個(gè)應(yīng)用系統(tǒng)的異常比如叫做AppException。并且對(duì)用戶來說,這些異常都是運(yùn)行應(yīng)用系統(tǒng)運(yùn)行時(shí)發(fā)生的,因此AppException應(yīng)該繼承RuntimeException,這樣系統(tǒng)中所有的其他異常都轉(zhuǎn)譯為AppException,當(dāng)異常發(fā)生的時(shí)候,前端接收到AppExcetpion并做統(tǒng)一的處理。畫出異常處理框架如圖 3 :

             

          3 一個(gè)應(yīng)用系統(tǒng)的異常處理框架

              在這個(gè)設(shè)計(jì)圖中,AppRuntimeException是系統(tǒng)異常的基類,對(duì)外只拋出這個(gè)異常,這個(gè)異常可以由前端(客戶端)接收處理,當(dāng)異常發(fā)生時(shí),客戶端的相關(guān)組件捕獲并處理這些異常,將"友好"的信息展示給客戶。

              在AppRuntimeException下層,有各種各樣的異常和錯(cuò)誤,最終都轉(zhuǎn)譯為AppRuntimeException,AppRuntimeException下面還可以設(shè)計(jì)一些別的子類異常,比如AppDAOException、OtherException等,這些都根據(jù)實(shí)際需要靈活處理。在往下就是如何將捕獲的原始異常比如SQLException、HibernateException轉(zhuǎn)換為更高級(jí)一點(diǎn)AppDAOException。

              有關(guān)異常框架設(shè)計(jì)這方面公認(rèn)比較好的就是Spring,Spring中的所有異常都可以用org.springframework.core.NestedRuntimeException來表示,并且該基類繼承的是RuntimeException。Spring框架很龐大,因此設(shè)計(jì)了很多NestedRuntimeException的子類,還有異常轉(zhuǎn)換的工具,這些都是非常優(yōu)秀的設(shè)計(jì)思想。

              六、 Java異常處理總結(jié)

              回顧全文,總結(jié)一下Java異常處理的要點(diǎn):

              1、 異常是程序運(yùn)行過程過程出現(xiàn)的錯(cuò)誤,在Java中用類來描述,用對(duì)象來表示具體的異常。Java將其區(qū)分為Error與Exception,Error是程序無力處理的錯(cuò)誤,Exception是程序可以處理的錯(cuò)誤。異常處理是為了程序的健壯性。
              2、 Java異常類來自于Java API定義和用戶擴(kuò)展。通過繼承Java API異常類可以實(shí)現(xiàn)異常的轉(zhuǎn)譯。
              3、 異常能處理就處理,不能處理就拋出,最終沒有處理的異常JVM會(huì)進(jìn)行處理。
              4、 異常可以傳播,也可以相互轉(zhuǎn)譯,但應(yīng)該根據(jù)需要選擇合理的異常轉(zhuǎn)譯的方向。
              5、 對(duì)于一個(gè)應(yīng)用系統(tǒng),設(shè)計(jì)一套良好的異常處理體系很重要。這一點(diǎn)在系統(tǒng)設(shè)計(jì)的時(shí)候就應(yīng)該考慮到。

          posted @ 2010-03-20 16:12 drecry 閱讀(213) | 評(píng)論 (0)編輯 收藏

          2009年6月1日 #

          (轉(zhuǎn))java 學(xué)習(xí),,從入門到精通

          轉(zhuǎn)自:http://forum.hibernate.org.cn
          作者:robbin
          Java Learning Path (一)、工具篇
          一、 JDK (Java Development Kit)

          JDK是整個(gè)Java的核心,包括了Java運(yùn)行環(huán)境(Java Runtime Envirnment),一堆Java工具和Java基礎(chǔ)的類庫(kù)(rt.jar)。不論什么Java應(yīng)用服務(wù)器實(shí)質(zhì)都是內(nèi)置了某個(gè)版本的JDK。因此掌握 JDK是學(xué)好Java的第一步。最主流的JDK是Sun公司發(fā)布的JDK,除了Sun之外,還有很多公司和組織都開發(fā)了自己的JDK,例如IBM公司開發(fā) 的JDK,BEA公司的Jrocket,還有GNU組織開發(fā)的JDK等等。其中IBM的JDK包含的JVM(Java Virtual Machine)運(yùn)行效率要比Sun JDK包含的JVM高出許多。而專門運(yùn)行在x86平臺(tái)的Jrocket在服務(wù)端運(yùn)行效率也要比Sun JDK好很多。但不管怎么說,我們還是需要先把Sun JDK掌握好。

          1、 JDK的下載和安裝
          JDK又叫做J2SE(Java2 SDK Standard Edition),可以從Sun的Java網(wǎng)站上下載到,http://java.sun.com/j2se/downloads.html ,JDK當(dāng)前最新的版本是J2SDK1.4.2,建議下載該版本的JDK,下載頁(yè)面在這里:http://java.sun.com/j2se /1.4.2/download.html。

          下載好的JDK是一個(gè)可執(zhí)行安裝程序,默認(rèn)安裝完畢后會(huì)在C:\Program Files\Java\目錄下安裝一套JRE(供瀏覽器來使用),在C:\j2sdk1.4.2下安裝一套JDK(也包括一套JRE)。然后我們需要在環(huán) 境變量PATH的最前面增加java的路徑C:\j2sdk1.4.2\bin。這樣JDK就安裝好了。

          2、 JDK的命令工具
          JDK的最重要命令行工具:
          java: 啟動(dòng)JVM執(zhí)行class
          javac: Java編譯器
          jar: Java打包工具
          javadoc: Java文檔生成器
          這些命令行必須要非常非常熟悉,對(duì)于每個(gè)參數(shù)都要很精通才行。對(duì)于這些命令的學(xué)習(xí),JDK Documentation上有詳細(xì)的文檔。


          二、 JDK Documentation

          Documentation在JDK的下載頁(yè)面也有下載連接,建議同時(shí)下載Documentation。Documentation是最最重要的編程手 冊(cè),涵蓋了整個(gè)Java所有方面的內(nèi)容的描述。可以這樣說,學(xué)習(xí)Java編程,大部分時(shí)間都是花在看這個(gè)Documentation上面的。我是隨身攜帶 的,寫Java代碼的時(shí)候,隨時(shí)查看,須臾不離手。


          三、 應(yīng)用服務(wù)器(App Server)

          App Server是運(yùn)行Java企業(yè)組件的平臺(tái),構(gòu)成了應(yīng)用軟件的主要運(yùn)行環(huán)境。當(dāng)前主流的App Server是BEA公司的Weblogic Server和IBM公司的Websphere以及免費(fèi)的Jboss,選擇其中一個(gè)進(jìn)行學(xué)習(xí)就可以了,個(gè)人推薦Weblogic,因?yàn)樗捏w系結(jié)構(gòu)更加干 凈,開發(fā)和部署更加方便,是Java企業(yè)軟件開發(fā)人員首選的開發(fā)平臺(tái)。下面簡(jiǎn)要介紹幾種常用的App Server:

          1、 Tomcat
          Tomcat嚴(yán)格意義上并不是一個(gè)真正的App Server,它只是一個(gè)可以支持運(yùn)行Serlvet/JSP的Web容器,不過Tomcat也擴(kuò)展了一些App Server的功能,如JNDI,數(shù)據(jù)庫(kù)連接池,用戶事務(wù)處理等等。Tomcat被非常廣泛的應(yīng)用在中小規(guī)模的Java Web應(yīng)用中,因此本文做一點(diǎn)下載、安裝和配置Tomcat的介紹:

          Tomcat是Apache組織下Jakarta項(xiàng)目下的一個(gè)子項(xiàng)目,它的主網(wǎng)站是:http://jakarta.apache.org/tomcat / ,Tomcat最新版本是Tomcat4.1.27,軟件下載的連接是:http://www.apache.org/dist/jakarta /tomcat-4/binaries/ 。

          下載Tomcat既可以直接下載zip包,也可以下載exe安裝包(個(gè)人建議zip更干凈些),不管哪種情況,下載完畢安裝好以后(zip直接解壓縮就可以了)。需要設(shè)置兩個(gè)環(huán)境變量:

          JAVA_HOME=C:\j2sdk1.4.2
          CATALINA_HOME=D:\tomcat4 (你的Tomcat安裝目錄)

          這樣就安裝好了,啟動(dòng)Tomcat運(yùn)行CATALINA_HOME\bin\startup.bat,關(guān)閉Tomcat運(yùn)行shutdown.bat腳 本。Tomcat啟動(dòng)以后,默認(rèn)使用8080端口,因此可以用瀏覽器訪問http://localhost:8080來測(cè)試Tomcat是否正常啟動(dòng)。

          Tomcat提供了兩個(gè)Web界面的管理工具,URL分別是:
          http://localhost:8080/admin/index.jsp
          http://localhost:8080/manager/html
          在啟用這兩個(gè)管理工具之前,先需要手工配置一下管理員用戶和口令。用一個(gè)文本工具打開CATALINA_HOME\conf\tomcat-users.xml這個(gè)文件,加入如下幾行:

          <role rolename="manager"/>;
          <role rolename="admin"/>;
          <user username="robbin" password="12345678" roles="admin,manager,tomcat"/>;

          這樣用戶“robbin”就具備了超級(jí)管理員權(quán)限。重新啟動(dòng)Tomcat以后,你就可以使用該用戶來登陸如上的兩個(gè)管理工具,通過Web方式進(jìn)行Tomcat的配置和管理了。

          2、 BEA Weblogic
          Weblogic可以到BEA的網(wǎng)站上免費(fèi)注冊(cè)之后下載到最新的Weblogic8.1企業(yè)版,License可以免費(fèi)使用1年時(shí)間,其實(shí)這已經(jīng)完全足夠 了。Weblogic的下載連接:http://commerce.bea.com/index.jsp,Weblogic的在線文檔:http: //edocs.bea.com/ 。

          3、 IBM Webshpere
          Websphere同樣可以下載到免費(fèi)的試用版本,到IBM的developerWorks網(wǎng)站可以看到Websphere試用產(chǎn)品的下載和相關(guān)的 Websphere的資料,developerWorks中文網(wǎng)站的連接是:http://www-900.ibm.com /developerWorks/cn/wsdd/ ,Websphere的下載連接:http://www7b.software.ibm.com/wsdd/downloads /WASsupport.html 。

          4、 Jboss
          Jboss是免費(fèi)開源的App Server,可以免費(fèi)的從Jboss網(wǎng)站下載:http://www.jboss.org/index.html,然而Jboss的文檔是不免費(fèi),需要 花錢購(gòu)買,所以為我們學(xué)習(xí)Jboss設(shè)置了一定的障礙。在Jdon上有幾篇不錯(cuò)的Jboss配置文檔,可以用來參 考:http://www.jdon.com/idea.html


          四、 Java應(yīng)用的運(yùn)行環(huán)境

          Java的應(yīng)用可以簡(jiǎn)單分為以下幾個(gè)方面:

          1、 Java的桌面應(yīng)用
          桌面應(yīng)用一般僅僅需要JRE的支持就足夠了。

          2、 Java Web應(yīng)用
          Java的Web應(yīng)用至少需要安裝JDK和一個(gè)web容器(例如Tomcat),以及一個(gè)多用戶數(shù)據(jù)庫(kù),Web應(yīng)用至少分為三層:
          Browser層:瀏覽器顯示用戶頁(yè)面
          Web層:運(yùn)行Servlet/JSP
          DB層:后端數(shù)據(jù)庫(kù),向Java程序提供數(shù)據(jù)訪問服務(wù)

          3、 Java企業(yè)級(jí)應(yīng)用
          企業(yè)級(jí)應(yīng)用比較復(fù)雜,可以擴(kuò)展到n層,最簡(jiǎn)單情況會(huì)分為4層:
          Browser層:瀏覽器顯示用戶頁(yè)面
          Client層:Java客戶端圖形程序(或者嵌入式設(shè)備的程序)直接和Web層或者EJB層交互
          Web層:運(yùn)行Servlet/JSP
          EJB層:運(yùn)行EJB,完成業(yè)務(wù)邏輯運(yùn)算
          DB層:后端數(shù)據(jù)庫(kù),向Java程序提供數(shù)據(jù)訪問服務(wù)

          4、 Java嵌入式應(yīng)用
          Java嵌入式應(yīng)用是一個(gè)方興未艾的領(lǐng)域,從事嵌入式開發(fā),需要從Sun下載J2ME開發(fā)包,J2ME包含了嵌入式設(shè)備專用虛擬機(jī)KVM,和普通的JDK中包含的JVM有所不同。另外還需要到特定的嵌入式廠商那里下載模擬器。


          Java Learning Path(二)、書籍篇

          學(xué)習(xí)一門新的知識(shí),不可能指望只看一本,或者兩本書就能夠完全掌握。需要有一個(gè)循序漸進(jìn)的閱讀過程。我推薦Oreilly出版的Java系列書籍。

          在這里我只想補(bǔ)充一點(diǎn)看法,很多人學(xué)習(xí)Java是從《Thinking in Java》這本書入手的,但是我認(rèn)為這本書是不適合初學(xué)者的。我認(rèn)為正確的使用這本書的方法應(yīng)該是作為輔助的讀物。《Thinking in Java》并不是在完整的介紹Java的整個(gè)體系,而是一種跳躍式的寫作方法,是一種類似tips的方法來對(duì)Java很多知識(shí)點(diǎn)進(jìn)行了深入的分析和解釋。

          對(duì)于初學(xué)者來說,最好是找一本Java入門的書籍,但是比較完整的循序的介紹Java的語(yǔ)法,面向?qū)ο蟮奶匦裕诵念悗?kù)等等,在看這本書的同時(shí), 可以同步來看《Thinking in Java》,來加深對(duì)Java的理解和原理的運(yùn)用,同時(shí)又可以完整的了解Java的整個(gè)體系。

          對(duì)于Java的入門書籍,蔡學(xué)鏞推薦的是Oreilly的《Exploring Java, 2nd Edition》 或者《Java in a Nutshell,2nd Edition(針對(duì)C++背景)》,我并沒有看過這兩本書。其實(shí)我覺得電子工業(yè)出版社的《Java 2編程詳解》或者《Java 2從入門到精通》就很不錯(cuò)。

          在所有的Java書籍當(dāng)中,其實(shí)最最有用的,并不是O'reilly的 Java Serials,真正最最有用處是JDK的Documentation!幾乎你想獲得的所有的知識(shí)在Documentation里面全部都有,其中最主要 的部分當(dāng)然是Java基礎(chǔ)類庫(kù)的API文檔,是按照package來組織的,對(duì)于每一個(gè)class都有詳細(xì)的解釋,它的繼承關(guān)系,是否實(shí)現(xiàn)了某個(gè)接口,通 常用在哪些場(chǎng)合,還可以查到它所有的public的屬性和方法,每個(gè)屬性的解釋,意義,每個(gè)方法的用途,調(diào)用的參數(shù),參數(shù)的意義,返回值的類型,以及方法 可能拋出的異常等等。可以這樣來說,所有關(guān)于Java編程方面的書籍其實(shí)都不過是在用比較通俗易懂的語(yǔ)言,和良好的組織方式來介紹 Documentation里面的某個(gè)package里面包含的一些類的用法而已。所以萬(wàn)變不離其宗,如果你有足夠的能力來直接通過 Documentation來學(xué)習(xí)Java的類庫(kù),那么基本上就不需要看其他的書籍了。除此之外,Documentation也是編程必備的手冊(cè),我的桌 面上有三個(gè)Documentation的快捷方式,分別是J2SDK1.4.1的Documentation,Servlet2.3的 Documentation和J2SDKEE1.3.1的Documentation。有了這個(gè)三個(gè)Documentation,什么其他的書籍都不需要 了。

          對(duì)于Java Web 編程來說,最核心的是要熟悉和掌握HTTP協(xié)議,這個(gè)就和Java無關(guān)了,在熟悉HTTP協(xié)議之后,就需要熟悉Java的實(shí)現(xiàn)HTTP協(xié)議的類庫(kù),也就是 Servlet API,所以最重要的東西就是Servlet API。當(dāng)然對(duì)于初學(xué)者而言,直接通過Servlet API來學(xué)習(xí)Web編程有很大的難度,我推薦O'reilly的《Java Server Pages 》這本書來學(xué)習(xí)Web 編程。

          EJB的書籍當(dāng)中,《Enterprise JavaBeans, 2nd Edition》是一本很不錯(cuò)的書, EJB的學(xué)習(xí)門檻是比較高,入門很難,但是這本書完全降低了學(xué)習(xí)的難度,特別重要的一點(diǎn)是,EJB的學(xué)習(xí)需要結(jié)合一種App Server的具體實(shí)現(xiàn),所以在學(xué)習(xí)EJB的同時(shí),必須同步的學(xué)習(xí)某種App Server,而這本書相關(guān)的出了三本書,分別是Weblogic6.1,Websphere4.0和JBoss3.0上面部署書中例子的實(shí)做。真是既有 理論,又有實(shí)踐。在學(xué)習(xí)EJB的同時(shí),可以邊看邊做,EJB的學(xué)習(xí)會(huì)變得很輕松。

          但是這本書也有一個(gè)問題,就是版本比較舊,主要講EJB1.1規(guī)范和部分EJB2.0的規(guī)范。而Ed Roman寫的《Mastering EJB 2.0》這本書完全是根據(jù)EJB2.0規(guī)范寫的,深入淺出,覆蓋了EJB編程的各個(gè)方面,并且還有很多編程經(jīng)驗(yàn)tips,也是學(xué)習(xí)EJB非常推薦的書籍之 一。

          如果是結(jié)合Weblogic來學(xué)習(xí)J2EE的話,《J2EE應(yīng)用與BEA Weblogic Server》絕對(duì)是首選讀物,雖然是講述的Weblogic6.0,仍然值得購(gòu)買,這本書是BEA官方推薦的教材,作者也是BEA公司的工程師。現(xiàn)在中 文版已經(jīng)隨處可見了。這本書結(jié)合Weblogic介紹了J2EE各個(gè)方面的技術(shù)在Weblogic平臺(tái)上的開發(fā)和部署,實(shí)踐指導(dǎo)意義非常強(qiáng)。

          在掌握了Java平臺(tái)基礎(chǔ)知識(shí)和J2EE方面的知識(shí)以后,更進(jìn)一步的是學(xué)習(xí)如何運(yùn)用OO的方法進(jìn)行軟件的設(shè)計(jì),那么就一定要學(xué)習(xí)“設(shè)計(jì)模式”。Sun公司 出版了一本《J2EE核心模式》,是每個(gè)開發(fā)Java企業(yè)平臺(tái)軟件的架構(gòu)師必備的書籍。這本書全面的介紹了J2EE體系架構(gòu)的各種設(shè)計(jì)模式,是設(shè)計(jì)師的必 讀書籍。

          Java Learning Path(三)過程篇

          每個(gè)人的學(xué)習(xí)方法是不同的,一個(gè)人的方法不見得適合另一個(gè)人,我只能是談自己的學(xué)習(xí)方法。因?yàn)槲覍W(xué)習(xí)Java是完全自學(xué)的,從來沒有問過別人,所以學(xué)習(xí)的過程基本上完全是自己摸索出來的。我也不知道這種方法是否是比較好的方法,只能給大家提供一點(diǎn)參考了。

          學(xué)習(xí)Java的第一步是安裝好JDK,寫一個(gè)Hello World,? 其實(shí)JDK的學(xué)習(xí)沒有那么簡(jiǎn)單,關(guān)于JDK有兩個(gè)問題是很容易一直困擾Java程序員的地方:一個(gè)是CLASSPATH的問題,其實(shí)從原理上來說,是要搞 清楚JRE的ClassLoader是如何加載Class的;另一個(gè)問題是package和import問題,如何來尋找類的路徑問題。把這兩個(gè)問題摸索 清楚了,就掃除了學(xué)習(xí)Java和使用JDK的最大障礙。推薦看一下王森的《Java深度歷險(xiǎn)》,對(duì)這兩個(gè)問題進(jìn)行了深入的探討。

          第二步是學(xué)習(xí)Java的語(yǔ)法。Java的語(yǔ)法是類C++的,基本上主流的編程語(yǔ)言不是類C,就是類C++的,沒有什么新東西,所以語(yǔ)法的學(xué)習(xí),大概就是半 天的時(shí)間足夠了。唯一需要注意的是有幾個(gè)不容易搞清楚的關(guān)鍵字的用法,public,protected,private,static,什么時(shí)候用,為 什么要用,怎么用,這可能需要有人來指點(diǎn)一下,我當(dāng)初是完全自己琢磨出來的,花了很久的時(shí)間。不過后來我看到《Thinking in Java》這本書上面是講了這些概念的。

          第三步是學(xué)習(xí)Java的面向?qū)ο蟮木幊陶Z(yǔ)言的特性的地方。比如繼承,構(gòu)造器,抽象類,接口,方法的多態(tài),重載,覆蓋,Java的異常處理機(jī)制。對(duì)于一個(gè)沒 有面向?qū)ο笳Z(yǔ)言背景的人來說,我覺得這個(gè)過程需要花很長(zhǎng)很長(zhǎng)時(shí)間,因?yàn)閷W(xué)習(xí)Java之前沒有C++的經(jīng)驗(yàn),只有C的經(jīng)驗(yàn),我是大概花了一個(gè)月左右吧,才徹 底把這些概念都搞清楚,把書上面的例子反復(fù)的揣摩,修改,嘗試,把那幾章內(nèi)容反復(fù)的看過來,看過去,看了不下5遍,才徹底領(lǐng)悟了。不過我想如果有C++經(jīng) 驗(yàn)的話,應(yīng)該一兩天時(shí)間足夠了。那么在這個(gè)過程中,可以多看看《Thinking in Java》這本書,對(duì)面向?qū)ο蟮闹v解非常透徹。可惜的是我學(xué)習(xí)的時(shí)候,并沒有看到這本書,所以自己花了大量的時(shí)間,通過自己的嘗試和揣摩來學(xué)會(huì)的。

          第四步就是開始熟悉Java的類庫(kù)。Java的基礎(chǔ)類庫(kù)其實(shí)就是JDK安裝目錄下面jre\lib\rt.jar這個(gè)包。學(xué)習(xí)基礎(chǔ)類庫(kù)就是學(xué)習(xí)rt.jar。基礎(chǔ)類庫(kù)里面的類非常非常多。據(jù)說有3000多個(gè),我沒有統(tǒng)計(jì)過。但是真正對(duì)于我們來說最核心的只有4個(gè),分別是
          java.lang.*;
          java.io.*;
          java.util.*;
          java.sql.*;

          這四個(gè)包的學(xué)習(xí),每個(gè)包的學(xué)習(xí)都可以寫成一本厚厚的教材,而O'reilly也確實(shí)是這樣做的。我覺得如果時(shí)間比較緊,是不可能通過讀四本書來學(xué)習(xí)。我覺得比較好的學(xué)習(xí)方法是這樣的:
          首先要通讀整個(gè)package的框架,了解整個(gè)package的class,interface,exception的構(gòu)成,最好是能夠找到介紹整個(gè)包框架的文章。這些專門介紹包的書籍的前幾章應(yīng)該就是這些總體的框架內(nèi)容介紹。

          對(duì)包整體框架的把握并不是要熟悉每個(gè)類的用法,記住它有哪些屬性,方法。想記也記不住的。而是要知道包有哪些方面的類構(gòu)成的,這些類的用途是什么,最核心 的幾個(gè)類分別是完成什么功能的。我在給人培訓(xùn)的時(shí)候一般是一次課講一個(gè)包,所以不可能詳細(xì)的介紹每個(gè)類的用法,但是我反復(fù)強(qiáng)調(diào),我給你們講這些包的不是要 告訴你們類的方法是怎么調(diào)用的,也不要求你們記住類的方法調(diào)用,而是要你們了解,Java給我們提供了哪些類,每個(gè)類是用在什么場(chǎng)合,當(dāng)我遇到問題的時(shí) 候,我知道哪個(gè)類,或者哪幾個(gè)類的組合可以解決我的問題,That'all!,當(dāng)我們具體寫程序的時(shí)候,只要你知道該用哪個(gè)類來完成你的工作就足夠了。編 碼的時(shí)候,具體的方法調(diào)用,是邊寫代碼,邊查Documentation,所有的東西都在Documentation里面,不要求你一定記住,實(shí)際你也記 不住3000多個(gè)類的總共將近10萬(wàn)個(gè)方法調(diào)用。所以對(duì)每個(gè)包的總體框架的把握就變得極為重要。

          第五步,通過上面的學(xué)習(xí),如果學(xué)的比較扎實(shí)的話,就打好了Java的基礎(chǔ)了,剩下要做的工作是掃清Documentation里面除了上面4個(gè)包之外的其 他一些比較有用處的類。相信進(jìn)展到這一步,Java的自學(xué)能力已經(jīng)被培養(yǎng)出來了,可以到了直接學(xué)習(xí)Documentation的水平了。除了要做GUI編 程之外,JDK里面其他會(huì)有用處的包是這些:
          java.text.*;
          java.net.*;
          javax.naming.*;
          這些包里面真正用的比較多的類其實(shí)很少,只有幾個(gè),所以不需要花很多時(shí)間。

          第六步,Java Web 編程
          Web編程的核心是HTTP協(xié)議,HTTP協(xié)議和Java無關(guān),如果不熟悉HTTP協(xié)議的話,雖然也可以學(xué)好Servlet/JSP編程,但是達(dá)不到舉一 反三,一通百通的境界。所以HTTP協(xié)議的學(xué)習(xí)是必備的。如果熟悉了HTTP協(xié)議的話,又有了Java編程的良好的基礎(chǔ),學(xué)習(xí)Servlet/JSP簡(jiǎn)直 易如反掌,我學(xué)習(xí)Servlet/JSP就用了不到一周的時(shí)間,然后就開始用JSP來做項(xiàng)目了。

          在Servlet/JSP的學(xué)習(xí)中,重頭仍然是Servlet Documentation。Servlet API最常用的類很少,花比較少的時(shí)間就可以掌握了。把這些類都看一遍,多寫幾個(gè)例子試試。Servlet/JSP編程本質(zhì)就是在反復(fù)調(diào)用這些類來通過 HTTP協(xié)議在Web Server和Brower之間交談。另外對(duì)JSP,還需要熟悉幾個(gè)常用JSP的標(biāo)記,具體的寫法記不住的話,臨時(shí)查就是了。

          此外Java Web編程學(xué)習(xí)的重點(diǎn)要放在Web Application的設(shè)計(jì)模式上,如何進(jìn)行業(yè)務(wù)邏輯的分析,并且進(jìn)行合理的設(shè)計(jì),按照MVC設(shè)計(jì)模式的要求,運(yùn)用Servlet和JSP分別完成不同 的邏輯層,掌握如何在Servlet和JSP之間進(jìn)行流程的控制和數(shù)據(jù)的共享,以及Web Application應(yīng)該如何配置和部署。

          第七步,J2EE編程
          以上的學(xué)習(xí)過程如果是比較順利的話,進(jìn)行到這一步,難度又陡然提高。因?yàn)樯厦娴闹R(shí)內(nèi)容都是只涉及一個(gè)方面,而像EJB,JMS,JTA等核心的J2EE規(guī)范往往是幾種Java技術(shù)的綜合運(yùn)用的結(jié)晶,所以掌握起來難度比較大。

          首先一定要學(xué)習(xí)好JNDI,JNDI是App Server定位服務(wù)器資源(EJB組件,Datasouce,JMS)查找方法,如果對(duì)JNDI不熟悉的話,EJB,JMS這些東西幾乎學(xué)不下去。 JNDI其實(shí)就是javax.naming.*這個(gè)包,運(yùn)用起來很簡(jiǎn)單。難點(diǎn)在于服務(wù)器資源文件的配置。對(duì)于服務(wù)器資源文件的配置,就需要看看專門的文檔 規(guī)范了,比如web.xml的寫法,ejb-jar.xml的寫法等等。針對(duì)每種不同的App Server,還有自己的服務(wù)資源配置文件,也是需要熟悉的。

          然后可以學(xué)習(xí)JTA,主要是要理解JTA對(duì)于事務(wù)的控制的方法,以及該在什么場(chǎng)合使用JTA。這里可以簡(jiǎn)單的舉個(gè)例子,我們知道一般情況可以對(duì)于一個(gè)數(shù)據(jù) 庫(kù)連接進(jìn)行事務(wù)控制(conn.setAutoCommit(false),....,conn.commit()),做為一個(gè)原子操作,但是假設(shè)我的業(yè) 務(wù)需求是要把對(duì)兩個(gè)不同數(shù)據(jù)庫(kù)的操作做為一個(gè)原子操作,你能做的到嗎?這時(shí)候只能用JTA了。假設(shè)操作過程是先往A數(shù)據(jù)庫(kù)插一條記錄,然后刪除B數(shù)據(jù)庫(kù)另 一個(gè)記錄,我們自己寫代碼是控制不了把整個(gè)操作做為一個(gè)原子操作的。用JTA的話,由App Server來完成控制。

          在學(xué)習(xí)EJB之前要學(xué)習(xí)對(duì)象序列化和RMI,RMI是EJB的基礎(chǔ)。接著學(xué)習(xí)JMS和EJB,對(duì)于EJB來說,最關(guān)鍵是要理解EJB是如何通過RMI來實(shí)現(xiàn)對(duì)遠(yuǎn)端對(duì)象的調(diào)用的,以及在什么情況下要用到EJB。

          在學(xué)習(xí)完EJB,JMS這些東西之后,你可能會(huì)意識(shí)到要急不可待學(xué)習(xí)兩個(gè)領(lǐng)域的知識(shí),一個(gè)是UML,另一個(gè)是Design Pattern。Java企業(yè)軟件的設(shè)計(jì)非常重視框架(Framework)的設(shè)計(jì),一個(gè)好的軟件框架是軟件開發(fā)成功的必要條件。在這個(gè)時(shí)候,應(yīng)該開始把 學(xué)習(xí)的重點(diǎn)放在設(shè)計(jì)模式和框架的學(xué)習(xí)上,通過學(xué)習(xí)和實(shí)際的編程經(jīng)驗(yàn)來掌握EJB的設(shè)計(jì)模式和J2EE的核心模式。

          J2EE規(guī)范里面,除了EJB,JMS,JTA,Servlet/JSP,JDBC之外還有很多很多的企業(yè)技術(shù),這里不一一進(jìn)行介紹了。

          另外還有一個(gè)最新領(lǐng)域Web Services。Web Services也完全沒有任何新東西,它像是一種黏合劑,可以把不同的服務(wù)統(tǒng)一起來提供一個(gè)統(tǒng)一的調(diào)用接口,作為使用者來說,我只要獲得服務(wù)提供者給我 的WSDL(對(duì)服務(wù)的描述),就夠了,我完全不知道服務(wù)器提供者提供的服務(wù)究竟是EJB組件,還是.Net組件,還是什么CORBA組件,還是其他的什么 實(shí)現(xiàn),我也不需要知道。Web Services最偉大的地方就在于通過統(tǒng)一的服務(wù)提供方式和調(diào)用方式,實(shí)現(xiàn)了整個(gè)Internet服務(wù)的共享,是一個(gè)非常令人激動(dòng)的技術(shù)領(lǐng)域。Web Services好像目前還沒有什么很好的書籍,但是可以通過在網(wǎng)絡(luò)上面查資料的方式來學(xué)習(xí)。

          Java Learning Path(四) 方法篇

          Java作為一門編程語(yǔ)言,最好的學(xué)習(xí)方法就是寫代碼。當(dāng)你學(xué)習(xí)一個(gè)類以后,你就可以自己寫個(gè)簡(jiǎn)單的例子程序來運(yùn)行一下,看看有什么結(jié)果,然后再多調(diào)用幾 個(gè)類的方法,看看運(yùn)行結(jié)果,這樣非常直觀的把類給學(xué)會(huì)了,而且記憶非常深刻。然后不應(yīng)該滿足把代碼調(diào)通,你應(yīng)該想想看如果我不這樣寫,換個(gè)方式,再試試行 不行。記得哪個(gè)高人說過學(xué)習(xí)編程就是個(gè)破壞的過程,把書上的例子,自己學(xué)習(xí)Documentation編寫的例子在運(yùn)行通過以后,不斷的嘗試著用不同的方 法實(shí)現(xiàn),不斷的嘗試破壞代碼的結(jié)構(gòu),看看它會(huì)有什么結(jié)果。通過這樣的方式,你會(huì)很徹底的很精通的掌握J(rèn)ava。

          舉個(gè)例子,我們都編過Hello World

          public class HelloWorld {
          public static void main(String[] args) {
          System.out.println("Hello World";
          }
          }

          很多初學(xué)者不是很理解為什么main方法一定要這樣來定義public static void main(String[] args),能不能不這樣寫?包括我剛學(xué)習(xí)Java的時(shí)候也有這樣的疑問。想知道答案嗎?很簡(jiǎn)單,你把main改個(gè)名字運(yùn)行一下,看看報(bào)什么錯(cuò)誤,然后根 據(jù)出錯(cuò)信息進(jìn)行分析;把main的public取掉,在試試看,報(bào)什么錯(cuò)誤;static去掉還能不能運(yùn)行;不知道m(xù)ain方法是否一定要傳一個(gè) String[]數(shù)組的,把String[]改掉,改成int[],或者String試試看;不知道是否必須寫args參數(shù)名稱的,也可以把a(bǔ)rgs改成 別的名字,看看運(yùn)行結(jié)果如何。

          我當(dāng)初學(xué)習(xí)Java的時(shí)候就是這樣做的,把Hello World程序反復(fù)改了七八次,不斷運(yùn)行,分析運(yùn)行結(jié)果,最后就徹底明白為什么了main方法是這樣定義的了。

          此外,我對(duì)于staic,public,private,Exception,try{ }catch {}finally{}等等等等一開始都不是很懂,都是把參考書上面的例子運(yùn)行成功,然后就開始破壞它,不斷的根據(jù)自己心里面的疑問來重新改寫程序,看看 能不能運(yùn)行,運(yùn)行出來是個(gè)什么樣子,是否可以得到預(yù)期的結(jié)果。這樣雖然比較費(fèi)時(shí)間,不過一個(gè)例子程序這樣反復(fù)破壞幾次之后。我就對(duì)這個(gè)相關(guān)的知識(shí)徹底學(xué)通 了。有時(shí)候甚至故意寫一些錯(cuò)誤的代碼來運(yùn)行,看看能否得到預(yù)期的運(yùn)行錯(cuò)誤。這樣對(duì)于編程的掌握是及其深刻的。

          其中特別值得一提的是JDK有一個(gè)非常棒的調(diào)試功能,-verbose
          java –verbose
          javac –verbose 以及其它很多JDK工具都有這個(gè)選項(xiàng)
          -verbose 可以顯示在命令執(zhí)行的過程中,JVM都依次加載哪里Class,通過這些寶貴的調(diào)試信息,可以幫助我們分析出JVM在執(zhí)行的過程中都干了些什么。

          另外,自己在學(xué)習(xí)過程中,寫的很多的這種破壞例程,應(yīng)該有意識(shí)的分門別類的保存下來,在工作中積累的典型例程也應(yīng)該定期整理,日積月累,自己就有了一個(gè)代 碼庫(kù)了。遇到類似的問題,到代碼庫(kù)里面 Copy & Paste ,Search & Replace,就好了,極大提高了開發(fā)速度。最理想的情況是把一些通用的例程自己再抽象一層,形成一個(gè)通用的類庫(kù),封裝好。那么可復(fù)用性就更強(qiáng)了。

          所以我覺得其實(shí)不是特別需要例程的,自己寫的破壞例程就是最好的例子,如果你實(shí)在對(duì)自己寫的代碼不放心的話,我強(qiáng)烈推薦你看看JDK基礎(chǔ)類庫(kù)的Java源 代碼。在JDK安裝目錄下面會(huì)有一個(gè)src.zip,解開來就可以完整的看到整個(gè)JDK基礎(chǔ)類庫(kù),也就是rt.jar的Java源代碼,你可以參考一下 Sun是怎么寫Java程序的,規(guī)范是什么樣子的。我自己在學(xué)習(xí)Java的類庫(kù)的時(shí)候,當(dāng)有些地方理解的不是很清楚的時(shí)候,或者想更加清晰的理解運(yùn)作的細(xì) 節(jié)的時(shí)候,往往會(huì)打開相應(yīng)的類的源代碼,通過看源代碼,所有的問題都會(huì)一掃而空。

          Java Learning Path(五)資源篇

          1、 http://java.sun.com/ (英文)
          Sun的Java網(wǎng)站,是一個(gè)應(yīng)該經(jīng)常去看的地方。不用多說。

          2、http://www-900.ibm.com/developerWorks/cn/
          IBM的developerWorks網(wǎng)站,英語(yǔ)好的直接去英文主站點(diǎn)看。這里不但是一個(gè)極好的面向?qū)ο蟮姆治鲈O(shè)計(jì)網(wǎng)站,也是Web Services,Java,Linux極好的網(wǎng)站。強(qiáng)烈推薦!!!

          3、http://www.javaworld.com/ (英文)
          關(guān)于Java很多新技術(shù)的討論和新聞。想多了解Java的方方面面的應(yīng)用,這里比較好。

          4、http://dev2dev.bea.com.cn/index.jsp
          BEA的開發(fā)者園地,BEA作為最重要的App Server廠商,有很多獨(dú)到的技術(shù),在Weblogic上做開發(fā)的朋友不容錯(cuò)過。

          5、http://www.huihoo.com/
          灰狐動(dòng)力網(wǎng)站,一個(gè)專業(yè)的中間件網(wǎng)站,雖然不是專業(yè)的Java網(wǎng)站,但是在J2EE企業(yè)應(yīng)用技術(shù)方面有深厚的造詣。

          6、http://www.theserverside.com/home/ (英文)
          TheServerSide是一個(gè)著名的專門面向Java Server端應(yīng)用的網(wǎng)站。

          7、http://www.javaresearch.org/
          Java研究組織,有很多優(yōu)秀的Java方面的文章和教程,特別是在JDO方面的文章比較豐富。

          8、http://www.cnjsp.org/
          JSP技術(shù)網(wǎng)站,有相當(dāng)多的Java方面的文章和資源。

          9、http://www.jdon.com/
          Jdon論壇,是一個(gè)個(gè)人性質(zhì)的中文J2EE專業(yè)技術(shù)論壇,在眾多的Java的中文論壇中,Jdon一個(gè)是技術(shù)含量非常高,帖子質(zhì)量非常好的論壇。

          10、http://sourceforge.net/
          SourgeForge是一個(gè)開放源代碼軟件的大本營(yíng),其中也有非常非常豐富的Java的開放源代碼的著名的軟件。
          _________________

          posted @ 2009-06-01 19:10 drecry 閱讀(249) | 評(píng)論 (0)編輯 收藏

          僅列出標(biāo)題  下一頁(yè)
          主站蜘蛛池模板: 榆中县| 屏东市| 黄龙县| 临朐县| 岳普湖县| 上林县| 洛川县| 昌都县| 太仆寺旗| 东方市| 阿瓦提县| 拜泉县| 兴安县| 饶平县| 邵东县| 金昌市| 米脂县| 健康| 连云港市| 沙洋县| 石屏县| 三原县| 凤冈县| 新郑市| 枞阳县| 遂昌县| 东山县| 正蓝旗| 崇礼县| 金川县| 开鲁县| 乌苏市| 田阳县| 东丽区| 柳江县| 喀什市| 赣榆县| 尖扎县| 无锡市| 平远县| 永平县|