<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java容器集合學習心得

    在Java中有許多的容器集合。初一看起來有些糊涂,特別是對剛接觸Java來說(至少我當初就是這樣的)!其實稍微細心,深入一點點就會發現原來一切都是有規律的。我想別的事情也會是如此。
    ???????Java中的容器,接口都是由一些接口,抽象類及它們的實現類所組成。而它們全部封裝在java.util
    包中。


    1:Collection接口。

    ?????? 大多數的集合都實現了此接口,它基本方法是add(沒有get()方法,實現類中可能有如Arrylist),添加一對象。添加成功則返回true ,否則返回false。這是與Map不同的地方。還有一些常用的方法如iterator(),size(),toArray()(注:toArray()是返回一對象----object數組,而Arrays----也是java.util下的一個類,有一個asList方法它們通常認為是各集合之間轉換的橋梁)等等!具體用法可以參考API文檔。


    2:Map(映射)
    ?????? Map接口跟Collection接口實際上沒有半點關系。集合中的每一個元素都包含一對鍵對對象和值對象,集合中沒有重復的鍵對象,值對象可以重復。它的有些實現類能對集合中的鍵對象進行排序。與Collection截然不同的是,它其中所存取的是一些值與名相對應的數據。也就是一個Key對應一個Value的方式來存儲。所以它就有與之對應的一些方法如:put (K key, V value)等等,更多可以參考API文檔。

    3:List(列表)
    ??????集合中的對象按索引位置排序,可以有重復對象,允許按照對象在集合中的索引位置檢索對象

    4:Set(集)
    ??????集合中的對象中按特定的方式排序,并且沒有重復對象。它的有些實現類能對集合中的對象
    按特定的方式排序

    5:迭代器:Iterator
    ?????? 它是一個接口,只有三個方法hasnext(),next(),remove()只有最后一個是可選的,也就是remove()是可選(在實現的時候)。其可選性也意味著它的實現類中,remove方法是可有可無的。例如,若有一個如下的List 實例。
    ????????
    ????Arrylist?al? = ? new ?Arrylist();
    ????Object[]?ob?
    = ?al.toArray();
    ????List?list?
    = ?Arrays.asList(ob);
    ????Iterator?itor?
    = ?list.iterator();
    ????itor.remove();??????
    // Error?

    ??????? 當調用Ierator itr = list.iterator()方法返回一迭代器的時候,便不支持remove方法,所以當你再使用irt.remove()時程序就是異常!

    ??????? 使用此迭代器要注意的是remove()方法。它所刪除的是指指針(暫這么叫著)上次所移經過的位置(Removes from the underlying collection the last element returned by the iterator (optional operation).)。我個人覺得有點象在JDBC中的ResultSet rs = ....;rs.last();rowsCount=rs.getRow();類似呢。
    ??????? 前面所講的,由于clollection提供了iterator()方法,所以迭代器是很容易實現的!

    6:常用實現類的一些繼承關系:

    ??????? Collections,它是Java.util下的一個類。它為我們提供了許多有用的方法,如sort(...),max()等其具體用法可以參考API文檔,比如sort(List list);中list內的所有元素都必須實現Comparable接口(All elements in the list must implement the Comparable interface)。

    ??????
    Arrylist,它是List接口的實現類,而List則是繼承于Collection。
    ???????LinkedList,它也是間接對Colections的實現。用linkedlist的一些方法如addfirst(),removefirst(),addlast()等等可以用來實現如C中的堆棧,鏈表。(對于頻繁使用插入與刪除操作使用linkedlist是個不錯的選擇,對于經常進行索引操作則arrylist較好)。


    ??????? HashSet(散列表),它實現了Set接口,也就意味著它的元素不能有重復值出現。并且在HashSet中沒有get()方法,但可以通過iterator()來實現。要注意的是假如要在HasSet中存放一些對象,那么你得重定義hashCode()與equals()二個方法來保不可以存放相同的內容的元素。對于hashcode()所返回的值,hashset用它來計算(通過特定的函數)該對象在內存中的存放位置;后者主要用來判斷二個對象的內容是否相等而返回對應的boolen型。
    ?????? TreeSet,主要用來對元素進行排序操作,假如要往其中添加對象,則對象得實現
    Comparable接口。(假如不要對元素排序,則一般可選用HashSet)。

    ???????HashMap,主要特點是存放的一個鍵值對,一些有用的方法是可返回視圖(我覺得可以把它理解為一個集合)如:keyset(),values(),entyset()等。
    ??????? TreeMap,它與HashMap差不多,不過是增加了對元素的排序功能,所以運行速度也就當然沒有hashmap來得快了。
    ?????????以下是HashMap的一個實例(在對DB進行操作的時候很有用):
    HashMap?valueMap;
    //this?function?just?get?key-value?form?DB?,defined?by?yourself
    valueMap?=?commondb.getElementStringValues("COMMENT_ID",?"content");
    java.util.Set?tempkeys?
    =?valueMap.entrySet();
    ????????????java.util.Iterator?keys?
    =?tempkeys.iterator();
    while(keys.hasNext())
    ????????????????
    {
    ????????????????????java.util.Map.Entry?me
    =(java.util.Map.Entry)keys.next();
    String?value?
    =?me.getValue();
    int?key?=?me.getKey();
    }


    ???????要注意的是entrySet()所返回的每一個元素都是Map.Entry類型的!(Returns a collection view of the mappings contained in this map. Each element in the returned collection is a Map.Entry.)??????
    ?
    ?????? Properties,繼承于hashtable。這個東東相信我們比較的喜歡了(在i18n,ant中可以是常見得很),呵呵。它可以從外部導入屬性文件。文件中的鍵值都是String類型。just like this:
    ????????
    company=study
    author
    =Jkallen
    copyright
    =2005-2006
    ???????
    ??????? ?操作如下:
    ???????
    import?java.util.*;
    import?java.io.*;
    class?PropTest
    {
    ????
    public?static?void?main(String[]?args)
    ????
    {
    ????????
    /*Properties?pps=System.getProperties();
    ????????pps.list(System.out);
    */

    ????????Properties?pps
    =new?Properties();
    ????????
    try
    ????????
    {
    ????????????pps.load(
    new?FileInputStream("winsun.ini"));
    ????????????Enumeration?
    enum=pps.propertyNames();
    ????????????
    while(enum.hasMoreElements())
    ????????????
    {
    ????????????????String?strKey
    =(String)enum.nextElement();
    ????????????????String?strValue
    =pps.getProperty(strKey);
    ????????????????
    ????????????????System.out.println(strKey
    +"="+strValue);
    ????????????}

    ????????}

    ????????
    catch(Exception?e)
    ????????
    {
    ????????????e.printStackTrace();
    ????????}

    ????}

    }

    ??????? 其用法可以查看API文檔呢。

    ??????? Java中的集合容器確實不少呢...其中有些我們也許一直都用不到,(我也是查看了些相關的資料再加上自己的一些想法整理了一下,希望對相關朋友有用!)可是重要的是知道我們在實現一個功能時應該選用哪種集合類來實現就OK了。

    posted @ 2006-06-09 15:57 nbt 閱讀(269) | 評論 (0)編輯 收藏

    介紹一篇關于session的好文章,寫的很詳細

    摘要:雖然session機制在web應用程序中被采用已經很長時間了,但是仍然有很多人不清楚session機制的本質,以至不能正確的應用這一技術。本文將詳細討論session的工作機制并且對在Java?web?application中應用session機制時常見的問題作出解答。

    目錄:
    一、術語session
    二、HTTP協議與狀態保持
    三、理解cookie機制
    四、理解session機制
    五、理解javax.servlet.http.HttpSession
    六、HttpSession常見問題
    七、跨應用程序的session共享
    八、總結
    參考文檔

    一、術語session
    在我的經驗里,session這個詞被濫用的程度大概僅次于transaction,更加有趣的是transaction與session在某些語境下的含義是相同的。

    session,中文經常翻譯為會話,其本來的含義是指有始有終的一系列動作/消息,比如打電話時從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個?session。有時候我們可以看到這樣的話“在一個瀏覽器會話期間,...”,這里的會話一詞用的就是其本義,是指從一個瀏覽器窗口打開到關閉這個期間?①。最混亂的是“用戶(客戶端)在一次會話期間”這樣一句話,它可能指用戶的一系列動作(一般情況下是同某個具體目的相關的一系列動作,比如從登錄到選購商品到結賬登出這樣一個網上購物的過程,有時候也被稱為一個transaction),然而有時候也可能僅僅是指一次連接,也有可能是指含義①,其中的差別只能靠上下文來推斷②。

    然而當session一詞與網絡協議相關聯時,它又往往隱含了“面向連接”和/或“保持狀態”這樣兩個含義,?“面向連接”指的是在通信雙方在通信之前要先建立一個通信的渠道,比如打電話,直到對方接了電話通信才能開始,與此相對的是寫信,在你把信發出去的時候你并不能確認對方的地址是否正確,通信渠道不一定能建立,但對發信人來說,通信已經開始了?!氨3譅顟B”則是指通信的一方能夠把一系列的消息關聯起來,使得消息之間可以互相依賴,比如一個服務員能夠認出再次光臨的老顧客并且記得上次這個顧客還欠店里一塊錢。這一類的例子有“一個TCP?session”或者?“一個POP3?session”③。

    而到了web服務器蓬勃發展的時代,session在web開發語境下的語義又有了新的擴展,它的含義是指一類用來在客戶端與服務器之間保持狀態的解決方案④。有時候session也用來指這種解決方案的存儲結構,如“把xxx保存在session?里”⑤。由于各種用于web開發的語言在一定程度上都提供了對這種解決方案的支持,所以在某種特定語言的語境下,session也被用來指代該語言的解決方案,比如經常把Java里提供的javax.servlet.http.HttpSession簡稱為session⑥。

    鑒于這種混亂已不可改變,本文中session一詞的運用也會根據上下文有不同的含義,請大家注意分辨。
    在本文中,使用中文“瀏覽器會話期間”來表達含義①,使用“session機制”來表達含義④,使用“session”表達含義⑤,使用具體的“HttpSession”來表達含義⑥

    二、HTTP協議與狀態保持
    HTTP?協議本身是無狀態的,這與HTTP協議本來的目的是相符的,客戶端只需要簡單的向服務器請求下載某些文件,無論是客戶端還是服務器都沒有必要紀錄彼此過去的行為,每一次請求之間都是獨立的,好比一個顧客和一個自動售貨機或者一個普通的(非會員制)大賣場之間的關系一樣。

    然而聰明(或者貪心?)的人們很快發現如果能夠提供一些按需生成的動態信息會使web變得更加有用,就像給有線電視加上點播功能一樣。這種需求一方面迫使HTML逐步添加了表單、腳本、DOM等客戶端行為,另一方面在服務器端則出現了CGI規范以響應客戶端的動態請求,作為傳輸載體的HTTP協議也添加了文件上載、?cookie這些特性。其中cookie的作用就是為了解決HTTP協議無狀態的缺陷所作出的努力。至于后來出現的session機制則是又一種在客戶端與服務器之間保持狀態的解決方案。

    讓我們用幾個例子來描述一下cookie和session機制之間的區別與聯系。筆者曾經常去的一家咖啡店有喝5杯咖啡免費贈一杯咖啡的優惠,然而一次性消費5杯咖啡的機會微乎其微,這時就需要某種方式來紀錄某位顧客的消費數量。想象一下其實也無外乎下面的幾種方案:
    1、該店的店員很厲害,能記住每位顧客的消費數量,只要顧客一走進咖啡店,店員就知道該怎么對待了。這種做法就是協議本身支持狀態。
    2、發給顧客一張卡片,上面記錄著消費的數量,一般還有個有效期限。每次消費時,如果顧客出示這張卡片,則此次消費就會與以前或以后的消費相聯系起來。這種做法就是在客戶端保持狀態。
    3、發給顧客一張會員卡,除了卡號之外什么信息也不紀錄,每次消費時,如果顧客出示該卡片,則店員在店里的紀錄本上找到這個卡號對應的紀錄添加一些消費信息。這種做法就是在服務器端保持狀態。

    由于HTTP協議是無狀態的,而出于種種考慮也不希望使之成為有狀態的,因此,后面兩種方案就成為現實的選擇。具體來說cookie機制采用的是在客戶端保持狀態的方案,而session機制采用的是在服務器端保持狀態的方案。同時我們也看到,由于采用服務器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要借助于cookie機制來達到保存標識的目的,但實際上它還有其他選擇。

    三、理解cookie機制?
    cookie機制的基本原理就如上面的例子一樣簡單,但是還有幾個問題需要解決:“會員卡”如何分發;“會員卡”的內容;以及客戶如何使用“會員卡”。

    正統的cookie分發是通過擴展HTTP協議來實現的,服務器通過在HTTP的響應頭中加上一行特殊的指示以提示瀏覽器按照指示生成相應的cookie。然而純粹的客戶端腳本如JavaScript或者VBScript也可以生成cookie。

    而cookie?的使用是由瀏覽器按照一定的原則在后臺自動發送給服務器的。瀏覽器檢查所有存儲的cookie,如果某個cookie所聲明的作用范圍大于等于將要請求的資源所在的位置,則把該cookie附在請求資源的HTTP請求頭上發送給服務器。意思是麥當勞的會員卡只能在麥當勞的店里出示,如果某家分店還發行了自己的會員卡,那么進這家店的時候除了要出示麥當勞的會員卡,還要出示這家店的會員卡。

    cookie的內容主要包括:名字,值,過期時間,路徑和域。
    其中域可以指定某一個域比如.google.com,相當于總店招牌,比如寶潔公司,也可以指定一個域下的具體某臺機器比如www.google.com或者froogle.google.com,可以用飄柔來做比。
    路徑就是跟在域名后面的URL路徑,比如/或者/foo等等,可以用某飄柔專柜做比。
    路徑與域合在一起就構成了cookie的作用范圍。
    如果不設置過期時間,則表示這個cookie的生命期為瀏覽器會話期間,只要關閉瀏覽器窗口,cookie就消失了。這種生命期為瀏覽器會話期的?cookie被稱為會話cookie。會話cookie一般不存儲在硬盤上而是保存在內存里,當然這種行為并不是規范規定的。如果設置了過期時間,瀏覽器就會把cookie保存到硬盤上,關閉后再次打開瀏覽器,這些cookie仍然有效直到超過設定的過期時間。

    存儲在硬盤上的cookie?可以在不同的瀏覽器進程間共享,比如兩個IE窗口。而對于保存在內存里的cookie,不同的瀏覽器有不同的處理方式。對于IE,在一個打開的窗口上按?Ctrl-N(或者從文件菜單)打開的窗口可以與原窗口共享,而使用其他方式新開的IE進程則不能共享已經打開的窗口的內存cookie;對于?Mozilla?Firefox0.8,所有的進程和標簽頁都可以共享同樣的cookie。一般來說是用javascript的window.open打開的窗口會與原窗口共享內存cookie。瀏覽器對于會話cookie的這種只認cookie不認人的處理方式經常給采用session機制的web應用程序開發者造成很大的困擾。

    下面就是一個goolge設置cookie的響應頭的例子
    HTTP/1.1?302?Found
    Location:?http://www.google.com/intl/zh-CN/
    Set-Cookie:?PREF=ID=0565f77e132de138:NW=1:TM=1098082649:LM=1098082649:S=KaeaCFPo49RiA_d8;?expires=Sun,?17-Jan-2038?19:14:07?GMT;?path=/;?domain=.google.com
    Content-Type:?text/html




    這是使用HTTPLook這個HTTP?Sniffer軟件來俘獲的HTTP通訊紀錄的一部分




    瀏覽器在再次訪問goolge的資源時自動向外發送cookie




    使用Firefox可以很容易的觀察現有的cookie的值
    使用HTTPLook配合Firefox可以很容易的理解cookie的工作原理。




    IE也可以設置在接受cookie前詢問




    這是一個詢問接受cookie的對話框。

    四、理解session機制
    session機制是一種服務器端的機制,服務器使用一種類似于散列表的結構(也可能就是使用散列表)來保存信息。

    當程序需要為某個客戶端的請求創建一個session的時候,服務器首先檢查這個客戶端的請求里是否已包含了一個session標識?-?稱為?session?id,如果已包含一個session?id則說明以前已經為此客戶端創建過session,服務器就按照session?id把這個?session檢索出來使用(如果檢索不到,可能會新建一個),如果客戶端請求不包含session?id,則為此客戶端創建一個session并且生成一個與此session相關聯的session?id,session?id的值應該是一個既不會重復,又不容易被找到規律以仿造的字符串,這個?session?id將被在本次響應中返回給客戶端保存。

    保存這個session?id的方式可以采用cookie,這樣在交互過程中瀏覽器可以自動的按照規則把這個標識發揮給服務器。一般這個cookie的名字都是類似于SEEESIONID,而。比如weblogic對于web應用程序生成的cookie,JSESSIONID=?ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764,它的名字就是?JSESSIONID。

    由于cookie可以被人為的禁止,必須有其他機制以便在cookie被禁止時仍然能夠把session?id傳遞回服務器。經常被使用的一種技術叫做URL重寫,就是把session?id直接附加在URL路徑的后面,附加方式也有兩種,一種是作為URL路徑的附加信息,表現形式為http://...../xxx;jsessionid=?ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
    另一種是作為查詢字符串附加在URL后面,表現形式為http://...../xxx?jsessionid=ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764
    這兩種方式對于用戶來說是沒有區別的,只是服務器在解析的時候處理的方式不同,采用第一種方式也有利于把session?id的信息和正常程序參數區分開來。
    為了在整個交互過程中始終保持狀態,就必須在每個客戶端可能請求的路徑后面都包含這個session?id。

    另一種技術叫做表單隱藏字段。就是服務器會自動修改表單,添加一個隱藏字段,以便在表單提交時能夠把session?id傳遞回服務器。比如下面的表單
    <form?name="testform"?action="/xxx">
    <input?type="text">
    </form>
    在被傳遞給客戶端之前將被改寫成
    <form?name="testform"?action="/xxx">
    <input?type="hidden"?name="jsessionid"?value="ByOK3vjFD75aPnrF7C2HmdnV6QZcEbzWoWiBYEnLerjQ99zWpBng!-145788764">
    <input?type="text">
    </form>
    這種技術現在已較少應用,筆者接觸過的很古老的iPlanet6(SunONE應用服務器的前身)就使用了這種技術。
    實際上這種技術可以簡單的用對action應用URL重寫來代替。

    在談論session機制的時候,常常聽到這樣一種誤解“只要關閉瀏覽器,session就消失了”。其實可以想象一下會員卡的例子,除非顧客主動對店家提出銷卡,否則店家絕對不會輕易刪除顧客的資料。對session來說也是一樣的,除非程序通知服務器刪除一個session,否則服務器會一直保留,程序一般都是在用戶做log?off的時候發個指令去刪除session。然而瀏覽器從來不會主動在關閉之前通知服務器它將要關閉,因此服務器根本不會有機會知道瀏覽器已經關閉,之所以會有這種錯覺,是大部分session機制都使用會話cookie來保存session?id,而關閉瀏覽器后這個?session?id就消失了,再次連接服務器時也就無法找到原來的session。如果服務器設置的cookie被保存到硬盤上,或者使用某種手段改寫瀏覽器發出的HTTP請求頭,把原來的session?id發送給服務器,則再次打開瀏覽器仍然能夠找到原來的session。

    恰恰是由于關閉瀏覽器不會導致session被刪除,迫使服務器為seesion設置了一個失效時間,當距離客戶端上一次使用session的時間超過這個失效時間時,服務器就可以認為客戶端已經停止了活動,才會把session刪除以節省存儲空間。

    五、理解javax.servlet.http.HttpSession
    HttpSession是Java平臺對session機制的實現規范,因為它僅僅是個接口,具體到每個web應用服務器的提供商,除了對規范支持之外,仍然會有一些規范里沒有規定的細微差異。這里我們以BEA的Weblogic?Server8.1作為例子來演示。

    首先,Weblogic?Server提供了一系列的參數來控制它的HttpSession的實現,包括使用cookie的開關選項,使用URL重寫的開關選項,session持久化的設置,session失效時間的設置,以及針對cookie的各種設置,比如設置cookie的名字、路徑、域,?cookie的生存時間等。

    一般情況下,session都是存儲在內存里,當服務器進程被停止或者重啟的時候,內存里的session也會被清空,如果設置了session的持久化特性,服務器就會把session保存到硬盤上,當服務器進程重新啟動或這些信息將能夠被再次使用,?Weblogic?Server支持的持久性方式包括文件、數據庫、客戶端cookie保存和復制。

    復制嚴格說來不算持久化保存,因為session實際上還是保存在內存里,不過同樣的信息被復制到各個cluster內的服務器進程中,這樣即使某個服務器進程停止工作也仍然可以從其他進程中取得session。

    cookie生存時間的設置則會影響瀏覽器生成的cookie是否是一個會話cookie。默認是使用會話cookie。有興趣的可以用它來試驗我們在第四節里提到的那個誤解。

    cookie的路徑對于web應用程序來說是一個非常重要的選項,Weblogic?Server對這個選項的默認處理方式使得它與其他服務器有明顯的區別。后面我們會專題討論。

    關于session的設置參考[5]?http://e-docs.bea.com/wls/docs70/webapp/weblogic_xml.html#1036869

    六、HttpSession常見問題
    (在本小節中session的含義為⑤和⑥的混合)


    1、session在何時被創建
    一個常見的誤解是以為session在有客戶端訪問時就被創建,然而事實是直到某server端程序調用?HttpServletRequest.getSession(true)這樣的語句時才被創建,注意如果JSP沒有顯示的使用?<%?@page?session="false"%>?關閉session,則JSP文件在編譯成Servlet時將會自動加上這樣一條語句?HttpSession?session?=?HttpServletRequest.getSession(true);這也是JSP中隱含的?session對象的來歷。

    由于session會消耗內存資源,因此,如果不打算使用session,應該在所有的JSP中關閉它。

    2、session何時被刪除
    綜合前面的討論,session在下列情況下被刪除a.程序調用HttpSession.invalidate();或b.距離上一次收到客戶端發送的session?id時間間隔超過了session的超時設置;或c.服務器進程被停止(非持久session)

    3、如何做到在瀏覽器關閉時刪除session
    嚴格的講,做不到這一點??梢宰鲆稽c努力的辦法是在所有的客戶端頁面里使用javascript代碼window.oncolose來監視瀏覽器的關閉動作,然后向服務器發送一個請求來刪除session。但是對于瀏覽器崩潰或者強行殺死進程這些非常規手段仍然無能為力。

    4、有個HttpSessionListener是怎么回事
    你可以創建這樣的listener去監控session的創建和銷毀事件,使得在發生這樣的事件時你可以做一些相應的工作。注意是session的創建和銷毀動作觸發listener,而不是相反。類似的與HttpSession有關的listener還有?HttpSessionBindingListener,HttpSessionActivationListener和?HttpSessionAttributeListener。

    5、存放在session中的對象必須是可序列化的嗎
    不是必需的。要求對象可序列化只是為了session能夠在集群中被復制或者能夠持久保存或者在必要時server能夠暫時把session交換出內存。在?Weblogic?Server的session中放置一個不可序列化的對象在控制臺上會收到一個警告。我所用過的某個iPlanet版本如果?session中有不可序列化的對象,在session銷毀時會有一個Exception,很奇怪。

    6、如何才能正確的應付客戶端禁止cookie的可能性
    對所有的URL使用URL重寫,包括超鏈接,form的action,和重定向的URL,具體做法參見[6]
    http://e-docs.bea.com/wls/docs70/webapp/sessions.html#100770

    7、開兩個瀏覽器窗口訪問應用程序會使用同一個session還是不同的session
    參見第三小節對cookie的討論,對session來說是只認id不認人,因此不同的瀏覽器,不同的窗口打開方式以及不同的cookie存儲方式都會對這個問題的答案有影響。

    8、如何防止用戶打開兩個瀏覽器窗口操作導致的session混亂
    這個問題與防止表單多次提交是類似的,可以通過設置客戶端的令牌來解決。就是在服務器每次生成一個不同的id返回給客戶端,同時保存在session里,客戶端提交表單時必須把這個id也返回服務器,程序首先比較返回的id與保存在session里的值是否一致,如果不一致則說明本次操作已經被提交過了??梢詤⒖础禞2EE核心模式》關于表示層模式的部分。需要注意的是對于使用javascript?window.open打開的窗口,一般不設置這個id,或者使用單獨的id,以防主窗口無法操作,建議不要再window.open打開的窗口里做修改操作,這樣就可以不用設置。

    9、為什么在Weblogic?Server中改變session的值后要重新調用一次session.setValue
    做這個動作主要是為了在集群環境中提示Weblogic?Server?session中的值發生了改變,需要向其他服務器進程復制新的session值。

    10、為什么session不見了
    排除session正常失效的因素之外,服務器本身的可能性應該是微乎其微的,雖然筆者在iPlanet6SP1加若干補丁的Solaris版本上倒也遇到過;瀏覽器插件的可能性次之,筆者也遇到過3721插件造成的問題;理論上防火墻或者代理服務器在cookie處理上也有可能會出現問題。
    出現這一問題的大部分原因都是程序的錯誤,最常見的就是在一個應用程序中去訪問另外一個應用程序。我們在下一節討論這個問題。

    七、跨應用程序的session共享

    常常有這樣的情況,一個大項目被分割成若干小項目開發,為了能夠互不干擾,要求每個小項目作為一個單獨的web應用程序開發,可是到了最后突然發現某幾個小項目之間需要共享一些信息,或者想使用session來實現SSO(single?sign?on),在session中保存login的用戶信息,最自然的要求是應用程序間能夠訪問彼此的session。

    然而按照Servlet規范,session的作用范圍應該僅僅限于當前應用程序下,不同的應用程序之間是不能夠互相訪問對方的session的。各個應用服務器從實際效果上都遵守了這一規范,但是實現的細節卻可能各有不同,因此解決跨應用程序session共享的方法也各不相同。

    首先來看一下Tomcat是如何實現web應用程序之間session的隔離的,從?Tomcat設置的cookie路徑來看,它對不同的應用程序設置的cookie路徑是不同的,這樣不同的應用程序所用的session?id是不同的,因此即使在同一個瀏覽器窗口里訪問不同的應用程序,發送給服務器的session?id也可以是不同的。


    ??

    根據這個特性,我們可以推測Tomcat中session的內存結構大致如下。




    筆者以前用過的iPlanet也采用的是同樣的方式,估計SunONE與iPlanet之間不會有太大的差別。對于這種方式的服務器,解決的思路很簡單,實際實行起來也不難。要么讓所有的應用程序共享一個session?id,要么讓應用程序能夠獲得其他應用程序的session?id。

    iPlanet中有一種很簡單的方法來實現共享一個session?id,那就是把各個應用程序的cookie路徑都設為/(實際上應該是/NASApp,對于應用程序來講它的作用相當于根)。
    <session-info>
    <path>/NASApp</path>
    </session-info>

    需要注意的是,操作共享的session應該遵循一些編程約定,比如在session?attribute名字的前面加上應用程序的前綴,使得?setAttribute("name",?"neo")變成setAttribute("app1.name",?"neo"),以防止命名空間沖突,導致互相覆蓋。


    在Tomcat中則沒有這么方便的選擇。在Tomcat版本3上,我們還可以有一些手段來共享session。對于版本4以上的Tomcat,目前筆者尚未發現簡單的辦法。只能借助于第三方的力量,比如使用文件、數據庫、JMS或者客戶端cookie,URL參數或者隱藏字段等手段。

    我們再看一下Weblogic?Server是如何處理session的。


    ??

    從截屏畫面上可以看到Weblogic?Server對所有的應用程序設置的cookie的路徑都是/,這是不是意味著在Weblogic?Server中默認的就可以共享session了呢?然而一個小實驗即可證明即使不同的應用程序使用的是同一個session,各個應用程序仍然只能訪問自己所設置的那些屬性。這說明Weblogic?Server中的session的內存結構可能如下




    對于這樣一種結構,在?session機制本身上來解決session共享的問題應該是不可能的了。除了借助于第三方的力量,比如使用文件、數據庫、JMS或者客戶端?cookie,URL參數或者隱藏字段等手段,還有一種較為方便的做法,就是把一個應用程序的session放到ServletContext中,這樣另外一個應用程序就可以從ServletContext中取得前一個應用程序的引用。示例代碼如下,

    應用程序A
    context.setAttribute("appA",?session);?

    應用程序B
    contextA?=?context.getContext("/appA");
    HttpSession?sessionA?=?(HttpSession)contextA.getAttribute("appA");?

    值得注意的是這種用法不可移植,因為根據ServletContext的JavaDoc,應用服務器可以處于安全的原因對于context.getContext("/appA");返回空值,以上做法在Weblogic?Server?8.1中通過。

    那么Weblogic?Server為什么要把所有的應用程序的cookie路徑都設為/呢?原來是為了SSO,凡是共享這個session的應用程序都可以共享認證的信息。一個簡單的實驗就可以證明這一點,修改首先登錄的那個應用程序的描述符weblogic.xml,把cookie路徑修改為/appA?訪問另外一個應用程序會重新要求登錄,即使是反過來,先訪問cookie路徑為/的應用程序,再訪問修改過路徑的這個,雖然不再提示登錄,但是登錄的用戶信息也會丟失。注意做這個實驗時認證方式應該使用FORM,因為瀏覽器和web服務器對basic認證方式有其他的處理方式,第二次請求的認證不是通過?session來實現的。具體請參看[7]?secion?14.8?Authorization,你可以修改所附的示例程序來做這些試驗。

    八、總結
    session機制本身并不復雜,然而其實現和配置上的靈活性卻使得具體情況復雜多變。這也要求我們不能把僅僅某一次的經驗或者某一個瀏覽器,服務器的經驗當作普遍適用的經驗,而是始終需要具體情況具體分析。
    摘要:雖然session機制在web應用程序中被采用已經很長時間了,但是仍然有很多人不清楚session機制的本質,以至不能正確的應用這一技術。本文將詳細討論session的工作機制并且對在Java?web?application中應用session機制時常見的問題作出解答。

    posted @ 2006-06-09 15:54 nbt 閱讀(289) | 評論 (0)編輯 收藏

    使用SOAP開發java web服務

    本文的預定讀者首先要對j2ee有所了解,熟悉xml,tomcat等基本內容,本文主要是簡單介紹一下web服務的基本內容,怎樣在java web開發中構建SOAP服務:
    ?一、SOAP(Simple Object Access Protocol)簡單對象訪問協議,要了解SOAP,首先就需要了解分布式計算的由來,隨著下一代的分布式計算體系web服務的出現,SOAP成為了創建和調用通過網絡發布的應用程序的實際通信標準。SOAP類似傳統的二進制協議IIOP(CORBA)和JRMP(RMI),但它不采用二進制數據表示法,而是采用使用XML的,基于文本的數據表示法。
    ??????? 通過XML表示法,SOAP定義了一種小型有線連接協議和編碼格式,以表示數據類型、編程語言和數據庫,還可以使用各種Internet標準協議作為其消息傳輸工具,還可以提供表示RPC和文檔驅動的消息交換等通信模型的約定。請注意,W3C正致力于SOAP的研究,http://www.w3c.org/2000/xp/Group/?,并得到了主流供應商的積極響應,以便對于基于XML的協議相關的重要任務達成共識,并定義其關鍵要求和使用場景。
    ??????? SOAP1.2的基本規范定義了以下基本內容:
    ?????? 1)用于將XML文檔表示為結構化SOAP消息的語法和語義
    ?????? 2)在SOAP消息中表示數據的編碼標準
    ?????? 3)用于交換SOAP消息的通信模型
    ???????4)SOAP傳輸等底層協議的綁定
    ????? SOAP消息主要包括了信封頭,消息頭,主體,附件幾部分
    ????? 一個簡單的SOAP消息表示:
    ????? POST?? /StudentInfo?? HTTP/1.1
    ????? Host:anthropology.cun.edu
    ????? Content-Type: text/xml;charset="utf-8"
    ????? Content-Length: 640
    ????? SOAPAction:??"GetStudentInfo"

    ???? <SOAP-ENV:Envelop xmlns:SOAP-ENV="http://www.w3c.org/2001/06/soap-envelope"
    ????????????? xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
    ??????????????xmlns:xsd="http://www.w3c.org/2001/XMLSchema"
    ???????????? SOAP-ENV:encodingStyle="http://www.w3c.org/2001/06/soap-encoding">
    ????????<SOAP-ENV:Header>
    ????????????<person:mail xmlns:person="http://www.cun.edu/Header">xyz@cun.edu
    ????????</SOAP-ENV:Header>?

    ????????<SOAP-ENV:Body>
    ????????????<m:GetStudentInfo?? xmlns:m="http://www.cun.edu/jws.student.studentInfo">
    ?????????????????<student_name xsi:type='xsd:string'>
    ????????????????????????Wang wen yin
    ?????????????????</student>
    ?????????????</m:GetStudentInfo>
    ????????</SOAP-ENV:Body>
    ????</SOAP-ENV:Envelop>
    ?? 以上是1.2版本命名空間,1.1的命名空間 SOAP ENVELOPE:http://schemas.xmlsoap.org/soap/envelop/ ,SOAP ENCODING: http://schemas.xmlsoap.org/soap/encoding/?
    ???關于SOAP編碼規范請參閱www.w3c.org/TR/xmlschema-2/?定義的編碼值,其他的一些規范可以上www.w3c.org 上具體查看。
    二、以下從實際例子來學習,這里我使用的是Apache的一個子項目Axis的具體例子,便于深入了解soap的運行:
    ??? 1)下載Axis的相關內容http://ws.apache.org/axis/
    ????2)建立一個實例程序(遵守j2ee的web程序規范),如(WebServiceTest目錄)
    ????????? 把axis中lib文件夾的內容拷到你的WebServiceTest/WEB-INF/lib下,同時上網下載xerces(下載地點:http://xml.apache.org/xerces-j/)解釋器的包文件xerces.jar,也拷到WebServiceTest/WEB-INF/lib文件夾下,(若要配置log4j,請把屬性文件log4j.properties拷到WebServiceTest/WEB-INF/classes文件夾下)
    ????3)修改應用程序WebServiceTest/WEB-INF中的web.xml文件:主要servlet設置如下
    ???????<servlet>
    ??????????????<servlet-name>TestServlet</servlet-name>
    ??????????????<servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
    ??????</servlet>
    ??????<servlet-mapping>
    ??????????????<servlet-name>TestServlet</servlet-name>
    ??????????????<url-pattern>*.jws</url-pattern>
    ?????</servlet-mapping>
    ?????<servlet-mapping>
    ??????????????<servlet-name>TestServlet</servlet-name>
    ??????????????<url-pattern>/servlet/TestServlet</url-pattern>
    ????</servlet-mapping>
    ??
    ????<servlet-mapping>
    ??????????????<servlet-name>TestServlet</servlet-name>
    ??????????????<url-pattern>/services/*</url-pattern>
    ?????</servlet-mapping>


    ?????<servlet>
    ??????????<servlet-name>AdminServlet</servlet-name>
    ??????????<servlet-class>
    ???????????????org.apache.axis.transport.http.AdminServlet
    ??????????</servlet-class>
    ??????????<load-on-startup>100</load-on-startup>
    ?????</servlet>
    ?
    ?????<servlet-mapping>
    ??????????<servlet-name>AdminServlet</servlet-name>
    ??????????<url-pattern>/servlet/AdminServlet</url-pattern>
    ?????</servlet-mapping>
    ?
    ?????<mime-mapping>
    ??????????<extension>wsdl</extension>
    ??????????<mime-type>text/xml</mime-type>
    ?????</mime-mapping>
    ?
    ?????<mime-mapping>
    ??????????<extension>xsd</extension>
    ??????????<mime-type>text/xml</mime-type>
    ?????</mime-mapping>
    ??? 你現在可以在網址里輸入http://localhost/WebServiceTest/servlet/TestServlet?看到了嗎?Axis是使用axis.jar包里的org.apache.axis.transport.http.AxisServlet對應用程序進行處理的,基本配置就講到這里。
    三、接著我們來說Axis中的內核。
    1)不使用Tomcat引擎運行Axis。
    ?????? 先建立一個腳步文件,對環境變量classpath進行設置要把lib下的那些包文件的路徑全都包括進去,運行:java??org.apache.axis.transport.http.SimpleAxisServer? <port>
    ?2)內部服務處理程序是org.apache.axis.providers.java.RPCProvider,標志出服務所需的方法,然后提供從SOAP請求消息組成部分的參數。
    ?3)Axis的應用程序端管理功能:
    ?????? java? org.apache.axis.client.AdminClient?就會列出參數,可供你選擇。我們的例子是:java? org.apache.axis.client.AdminClient? -l http://localhost/WebserviceTest/servlet/TestServlet? list 就會顯示出服務列表,返回的是xml文件
    4)wsdl2java應用程序可以把wsdl文件創建基于java的程序,如占位程序等
    ???? java? org.apache.axis.wsdl.WSDL2java? <url>
    Axis的基本內容說到這里
    四、具體例子
    ?1)編寫邏輯程序,簡單如:SoapTest.java
    ????public class SoapTest{
    ????????public String getStr(String name){
    ????????????return "Hello,"+name;
    ????????}
    ????}
    ? 2)?部署服務,編寫wsdd文件SoapTest_deploy.wsdd:
    ???? <deployment name="SimapleTest" xmlns="http://xml.apache.org/axis/wsdd/"
    ?????????xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
    ?????????xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
    ?????????xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
    ?????????????<service name="SoapTest" provider="java:RPC">
    ??????????????????<parameter name="className" value="SoapTest"/>
    ??????????????????<parameter name="allowedMethods" value="getStr"/>
    ?????????????</service>
    ????</deployment>
    ????其中className參數是你的想部署的類名(全名),allowedMethods是調用的服務的方法,如果有多個方法的話可以用空格分開(如:?<parameter name="allowedMethods" value="getStr? getMoney"/>),當用*的時候表示全部。
    ?????好了現在準備部署了,確保環境路徑classpath設置正確,運行:
    ????????java? org.apache.axis.client.AdminClient? -l? http://localhost/WebserviceTest/servlet/TestServlet? SoapTest_deploy.wsdd
    ?????(這里不懂的話,請參考以上的說明)?
    ?ok,呵呵,至此,我們已經完成了一個web服務的部署:測試http://localhost/WebServiceTest/servlet/TestServlet? 看里面是否多了一個選擇SoapTest服務?
    ????? 如果不想要服務了那重新編寫一個wsdd文件,內容改為:
    <deployment name="SimapleTest" xmlns="http://xml.apache.org/axis/wsdd/"
    ?????????xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
    ?????????xmlns:xsd="http://www.w3.org/2000/10/XMLSchema"
    ?????????xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
    ????????????<service name="SoapTest"/>
    </deployment>
    和上面一樣,對比一下就ok了。
    五、客戶端測試:
    ???? 客戶端我們也可以使用java來進行測試,網上也有資料的,你可以去學習,很簡單的?,F在為了體現web服務的魅力,我用.NET平臺來測試吧,客戶端使用c#編寫(先要安裝.net framework sdk):
    ??? 1)通過wsdl生成web服務代理,在net平臺下運行:
    ??????wsdl? /l:CS? /protocol:SOAP? /out:SoapTestClient.cs? http://localhost/WebserviceTest/services/SoapTest?wsdl??
    ??????? 我們通過wsdl得到了一個cs文件SoapTestClient.cs(當前目錄),你可以打開cs文件,研究一下里面的代碼,那個getStr(string name)就是我們需要調用的方法,我們的客戶端通過調用該方法就可以調用服務器端的方法,內部的轉化wsdl.exe工具已經幫我們完成了,axis下的WSDL2Java工具也是一樣的功能,可以參考我上面所說的關于Axis的內核內容
    ???2)編譯cs文件成程序集dll:
    ????? csc /target:library /r:System.Web.Services.dll? /r:System.Xml.dll SoapTestClient.cs
    ????? 最后我們等到了一個dll文件SoapTestClient.dll,客戶端程序通過調用它就行了
    ???3)編寫客戶端應用程序SoapTestClientApp.cs
    ????? using System;
    ??????
    ??????namespache? jws.client{
    ?????????public class SoapTestClientApp{
    ????????????public SoapTestClientApp(){
    ????????????}
    ????????????public static void?Main(string[] args){
    ????????????????if(args.Length!=1){
    ????????????????????Console.WriteLine("Usage:SoapTestClientApp <name>");
    ????????????????????Environment.Exit(1);
    ????????????????}
    ????????????????SoapTestService? st_service=new SoapTestService();
    ????????????????st_service.getStr("Wang wenyin");
    ???????????}
    ????????}?
    ?????}
    4)編譯文件csc? /r:SoapTestClient.dll? SoapTestClientApp.cs
    ????運行SoapTestClientApp
    輸出結果:
    ?????Hello,Wang wenyin
    與預期結果相符。

    posted @ 2006-06-09 15:51 nbt 閱讀(1247) | 評論 (0)編輯 收藏

    Hibernate的JNDI綁定分析

    Hibernate的JNDI名稱綁定是在net.sf.hibernate.impl.SessionFactoryObjectFactory程序里面實現的,我來分析一下Hibernate的綁定JNDI的過程:

    我們獲得SessionFactory一般是這樣寫代碼:

    Configuration conf = new Configuration().addClass(Cat.class);
    SessionFactory sf = conf.buildSessionFactory();

    首先是new Configuration()創建一個Configuration,在這個構造器里面進行配置文件(hibernate.properties)的讀取工作,然后保存到一個Properties對象里面去,和JNDI相關的是這個屬性:

    hibernate.session_factory_name hibernate/session_factory

    接著調用buildSessionFactory()方法,該方法檢查一下配置信息,然后調用SessionFactoryImpl的一個構造器。在構造器里面注意下面兩行代碼:

    name = properties.getProperty(Environment.SESSION_FACTORY_NAME);
    SessionFactoryObjectFactory.addInstance(uuid, name, this, properties);

    調用了SessionFactoryObjectFactory的addInstance方法,并且把自身(SessionFactory的實例)作為參數傳遞。最后在addInstance方法可以看到如下代碼:

    Context ctx = NamingHelper.getInitialContext(properties);
    NamingHelper.bind(ctx, name, instance);

    instance 就是SessionFactory的實例,通過讀源代碼,可以清楚的看到Hibernate是在conf.buildSessionFactory()的時候通過一系列類方法調用,把創建的SessionFactory實例綁定到配置文件(hibernate.properties)中 hibernate.session_factory_name屬性指定的名稱上的,因此可見Hibernate自身是具有JNDI的動態綁定功能的。但是Hibernate需要獲得一個SessionFactory實例用于綁定,而這個SessionFactory實例需要我們寫代碼進行預先創建,并且必須保證該過程要在所有其它要從JNDI上獲得SessionFactory實例的程序之前完成。

    因此對于任何App Server來說,我們都不必去管JNDI名稱的綁定過程,只需要保證預先創建一個SessionFactory實例出來就夠了,剩下的工作 Hibernate會做的。那么如何確保預創建SessionFactory實例呢,如果是Servlet,可以配置一個初始化的Servlet,只要把

    Configuration conf = new Configuration().addClass(Cat.class);
    SessionFactory sf = conf.buildSessionFactory();

    這樣的代碼加進去就可以了。如果是包含EJB的的復雜的J2EE應用,可能需要依靠App Server的功能來保證預創建SessionFactory實例。

    posted @ 2006-06-09 15:49 nbt 閱讀(229) | 評論 (0)編輯 收藏

    深入理解abstract class和interface

    abstract?class和interface是Java語言中對于抽象類定義進行支持的兩種機制,正是由于這兩種機制的存在,才賦予了Java強大的面向對象能力。abstract?class和interface之間在對于抽象類定義的支持方面具有很大的相似性,甚至可以相互替換,因此很多開發者在進行抽象類定義時對于abstract?class和interface的選擇顯得比較隨意。其實,兩者之間還是有很大的區別的,對于它們的選擇甚至反映出對于問題領域本質的理解、對于設計意圖的理解是否正確、合理。本文將對它們之間的區別進行一番剖析,試圖給開發者提供一個在二者之間進行選擇的依據。?

    理解抽象類?

    abstract?class和interface在Java語言中都是用來進行抽象類(本文中的抽象類并非從abstract?class翻譯而來,它表示的是一個抽象體,而abstract?class為Java語言中用于定義抽象類的一種方法,請讀者注意區分)定義的,那么什么是抽象類,使用抽象類能為我們帶來什么好處呢??

    在面向對象的概念中,我們知道所有的對象都是通過類來描繪的,但是反過來卻不是這樣。并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。抽象類往往用來表征我們在對問題領域進行分析、設計中得出的抽象概念,是對一系列看上去不同,但是本質上相同的具體概念的抽象。比如:如果我們進行一個圖形編輯軟件的開發,就會發現問題領域存在著圓、三角形這樣一些具體概念,它們是不同的,但是它們又都屬于形狀這樣一個概念,形狀這個概念在問題領域是不存在的,它就是一個抽象概念。正是因為抽象的概念在問題領域沒有對應的具體概念,所以用以表征抽象概念的抽象類是不能夠實例化的。?

    在面向對象領域,抽象類主要用來進行類型隱藏。我們可以構造出一個固定的一組行為的抽象描述,但是這組行為卻能夠有任意個可能的具體實現方式。這個抽象描述就是抽象類,而這一組任意個可能的具體實現則表現為所有可能的派生類。模塊可以操作一個抽象體。由于模塊依賴于一個固定的抽象體,因此它可以是不允許修改的;同時,通過從這個抽象體派生,也可擴展此模塊的行為功能。熟悉OCP的讀者一定知道,為了能夠實現面向對象設計的一個最核心的原則OCP(Open-Closed?Principle),抽象類是其中的關鍵所在。?


    從語法定義層面看abstract?class和interface?

    在語法層面,Java語言對于abstract?class和interface給出了不同的定義方式,下面以定義一個名為Demo的抽象類為例來說明這種不同。?

    使用abstract?class的方式定義Demo抽象類的方式如下:?

    abstract?class?Demo?{?
    ?abstract?void?method1();?
    ?abstract?void?method2();?
    ?…?
    }?

    使用interface的方式定義Demo抽象類的方式如下:?

    interface?Demo?{?
    ?void?method1();?
    ?void?method2();?
    ?…?
    }?

    在abstract?class方式中,Demo可以有自己的數據成員,也可以有非abstarct的成員方法,而在interface方式的實現中,Demo只能夠有靜態的不能被修改的數據成員(也就是必須是static?final的,不過在interface中一般不定義數據成員),所有的成員方法都是abstract的。從某種意義上說,interface是一種特殊形式的abstract?class。?

    ??????從編程的角度來看,abstract?class和interface都可以用來實現"design?by?contract"的思想。但是在具體的使用上面還是有一些區別的。?

    首先,abstract?class在Java語言中表示的是一種繼承關系,一個類只能使用一次繼承關系。但是,一個類卻可以實現多個interface。也許,這是Java語言的設計者在考慮Java對于多重繼承的支持方面的一種折中考慮吧。?

    其次,在abstract?class的定義中,我們可以賦予方法的默認行為。但是在interface的定義中,方法卻不能擁有默認行為,為了繞過這個限制,必須使用委托,但是這會?增加一些復雜性,有時會造成很大的麻煩。?

    在抽象類中不能定義默認行為還存在另一個比較嚴重的問題,那就是可能會造成維護上的麻煩。因為如果后來想修改類的界面(一般通過abstract?class或者interface來表示)以適應新的情況(比如,添加新的方法或者給已用的方法中添加新的參數)時,就會非常的麻煩,可能要花費很多的時間(對于派生類很多的情況,尤為如此)。但是如果界面是通過abstract?class來實現的,那么可能就只需要修改定義在abstract?class中的默認行為就可以了。?

    同樣,如果不能在抽象類中定義默認行為,就會導致同樣的方法實現出現在該抽象類的每一個派生類中,違反了"one?rule,one?place"原則,造成代碼重復,同樣不利于以后的維護。因此,在abstract?class和interface間進行選擇時要非常的小心。?


    從設計理念層面看abstract?class和interface?

    上面主要從語法定義和編程的角度論述了abstract?class和interface的區別,這些層面的區別是比較低層次的、非本質的。本小節將從另一個層面:abstract?class和interface所反映出的設計理念,來分析一下二者的區別。作者認為,從這個層面進行分析才能理解二者概念的本質所在。?

    前面已經提到過,abstarct?class在Java語言中體現了一種繼承關系,要想使得繼承關系合理,父類和派生類之間必須存在"is?a"關系,即父類和派生類在概念本質上應該是相同的(參考文獻〔3〕中有關于"is?a"關系的大篇幅深入的論述,有興趣的讀者可以參考)。對于interface?來說則不然,并不要求interface的實現者和interface定義在概念本質上是一致的,僅僅是實現了interface定義的契約而已。為了使論述便于理解,下面將通過一個簡單的實例進行說明。?

    考慮這樣一個例子,假設在我們的問題領域中有一個關于Door的抽象概念,該Door具有執行兩個動作open和close,此時我們可以通過abstract?class或者interface來定義一個表示該抽象概念的類型,定義方式分別如下所示:?

    使用abstract?class方式定義Door:?

    abstract?class?Door?{?
    ?abstract?void?open();?
    ?abstract?void?close();?
    }?

    ??
    使用interface方式定義Door:?


    interface?Door?{?
    ?void?open();?
    ?void?close();?
    }?

    ??
    其他具體的Door類型可以extends使用abstract?class方式定義的Door或者implements使用interface方式定義的Door??雌饋砗孟袷褂胊bstract?class和interface沒有大的區別。?

    如果現在要求Door還要具有報警的功能。我們該如何設計針對該例子的類結構呢(在本例中,主要是為了展示abstract?class和interface反映在設計理念上的區別,其他方面無關的問題都做了簡化或者忽略)?下面將羅列出可能的解決方案,并從設計理念層面對這些不同的方案進行分析。?

    解決方案一:?

    簡單的在Door的定義中增加一個alarm方法,如下:?

    abstract?class?Door?{?
    ?abstract?void?open();?
    ?abstract?void?close();?
    ?abstract?void?alarm();?
    }?

    ??
    或者?

    interface?Door?{?
    ?void?open();?
    ?void?close();?
    ?void?alarm();?
    }?

    ??
    那么具有報警功能的AlarmDoor的定義方式如下:?

    class?AlarmDoor?extends?Door?{?
    ?void?open()?{?…?}?
    ?void?close()?{?…?}?
    ?void?alarm()?{?…?}?
    }?

    ??
    或者?

    class?AlarmDoor?implements?Door?{?
    ?void?open()?{?…?}?
    ?void?close()?{?…?}?
    ?void?alarm()?{?…?}?
    }?

    這種方法違反了面向對象設計中的一個核心原則ISP(Interface?Segregation?Priciple),在Door的定義中把Door概念本身固有的行為方法和另外一個概念"報警器"的行為方法混在了一起。這樣引起的一個問題是那些僅僅依賴于Door這個概念的模塊會因為"報警器"這個概念的改變(比如:修改alarm方法的參數)而改變,反之依然。?

    解決方案二:?

    既然open、close和alarm屬于兩個不同的概念,根據ISP原則應該把它們分別定義在代表這兩個概念的抽象類中。定義方式有:這兩個概念都使用abstract?class方式定義;兩個概念都使用interface方式定義;一個概念使用abstract?class方式定義,另一個概念使用interface方式定義。?

    顯然,由于Java語言不支持多重繼承,所以兩個概念都使用abstract?class方式定義是不可行的。后面兩種方式都是可行的,但是對于它們的選擇卻反映出對于問題領域中的概念本質的理解、對于設計意圖的反映是否正確、合理。我們一一來分析、說明。?

    如果兩個概念都使用interface方式來定義,那么就反映出兩個問題:1、我們可能沒有理解清楚問題領域,AlarmDoor在概念本質上到底是Door還是報警器?2、如果我們對于問題領域的理解沒有問題,比如:我們通過對于問題領域的分析發現AlarmDoor在概念本質上和Door是一致的,那么我們在實現時就沒有能夠正確的揭示我們的設計意圖,因為在這兩個概念的定義上(均使用interface方式定義)反映不出上述含義。?

    如果我們對于問題領域的理解是:AlarmDoor在概念本質上是Door,同時它有具有報警的功能。我們該如何來設計、實現來明確的反映出我們的意思呢?前面已經說過,abstract?class在Java語言中表示一種繼承關系,而繼承關系在本質上是"is?a"關系。所以對于Door這個概念,我們應該使用abstarct?class方式來定義。另外,AlarmDoor又具有報警功能,說明它又能夠完成報警概念中定義的行為,所以報警概念可以通過interface方式定義。如下所示:?

    abstract?class?Door?{?
    ?abstract?void?open();?
    ?abstract?void?close();?
    }?
    interface?Alarm?{?
    ?void?alarm();?
    }?
    class?AlarmDoor?extends?Door?implements?Alarm?{?
    ?void?open()?{?…?}?
    ?void?close()?{?…?}?
    ????void?alarm()?{?…?}?
    }?

    ??
    這種實現方式基本上能夠明確的反映出我們對于問題領域的理解,正確的揭示我們的設計意圖。其實abstract?class表示的是"is?a"關系,interface表示的是"like?a"關系,大家在選擇時可以作為一個依據,當然這是建立在對問題領域的理解上的,比如:如果我們認為AlarmDoor在概念本質上是報警器,同時又具有Door的功能,那么上述的定義方式就要反過來了。?



    結論?

    abstract?class和interface是Java語言中的兩種定義抽象類的方式,它們之間有很大的相似性。但是對于它們的選擇卻又往往反映出對于問題領域中的概念本質的理解、對于設計意圖的反映是否正確、合理,因為它們表現了概念間的不同的關系(雖然都能夠實現需求的功能)。這其實也是語言的一種的慣用法,希望讀者朋友能夠細細體會。

    posted @ 2006-06-09 15:42 nbt 閱讀(191) | 評論 (0)編輯 收藏

    AOP編程入門(轉載)

    Aspect Oriented Programming(AOP),面向切面編程,是一個比較熱門的話題。AOP主要實現的目的是針對業務處理過程中的切面進行提取,它所面對的是處理過程中的某個步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。比如我們最常見的就是日志記錄了,舉個例子,我們現在提供一個服務查詢學生信息的,但是我們希望記錄有誰進行了這個查詢。如果按照傳統的OOP的實現的話,那我們實現了一個查詢學生信息的服務接口(StudentInfoService)和其實現類(StudentInfoServiceImpl.java),同時為了要進行記錄的話,那我們在實現類(StudentInfoServiceImpl.java)中要添加其實現記錄的過程。這樣的話,假如我們要實現的服務有多個呢?那就要在每個實現的類都添加這些記錄過程。這樣做的話就會有點繁瑣,而且每個實現類都與記錄服務日志的行為緊耦合,違反了面向對象的規則。那么怎樣才能把記錄服務的行為與業務處理過程中分離出來呢?看起來好像就是查詢學生的服務自己在進行,但是背后日志記錄對這些行為進行記錄,但是查詢學生的服務不知道存在這些記錄過程,這就是我們要討論AOP的目的所在。AOP的編程,好像就是把我們在某個方面的功能提出來與一批對象進行隔離,這樣與一批對象之間降低了耦合性,可以就某個功能進行編程。
    ????我們直接從代碼入手吧,要實現以上的目標,我們可以使用一個動態代理類(Proxy),通過攔截一個對象的行為并添加我們需要的功能來完成。Java中的java.lang.reflect.Proxy類和java.lang.reflect.InvocationHandler接口為我們實現動態代理類提供了一個方案,但是該方案針對的對象要實現某些接口;如果針對的目的是類的話,cglib為我們提供了另外一個實現方案。等下會說明兩者的區別。
    一、接口的實現方案:
    1)首先編寫我們的業務接口(StudentInfoService.java):
    public interface StudentInfoService{
    ?void findInfo(String studentName);
    }
    ???? 及其實現類(StudentInfoServiceImpl.java):
    public class StudentInfoServiceImpl implements StudentInfoService{
    ?public void findInfo(String name){
    ??System.out.println("你目前輸入的名字是:"+name);
    ?}
    }
    2)現在我們需要一個日志功能,在findInfo行為之前執行并記錄其行為,那么我們就首先要攔截該行為。在實際執行的過程中用一個代理類來替我們完成。Java中為我們提供了實現動態代理類的方案:

    1'處理攔截目的的類(MyHandler.java)
    import org.apache.log4j.Logger;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    import java.lang.reflect.Method;

    public class MyHandler implements InvocationHandler{
    ?private Object proxyObj;
    ?private static Logger log=Logger.getLogger(MyHandler.class);
    ?
    ?public Object bind(Object obj){
    ??this.proxyObj=obj;
    ??return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
    ?}
    ?
    ?public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
    ??Object result=null;
    ??try{
    ???//請在這里插入代碼,在方法前調用
    ???log.info("調用log日志方法"+method.getName());
    ???result=method.invoke(proxyObj,args); //原方法
    ???//請在這里插入代碼,方法后調用
    ??}catch(Exception e){
    ???e.printStackTrace();
    ??}
    ??return result;
    ?}
    }
    2'我們實現一個工廠,為了方便我們使用該攔截類(AOPFactory.java):
    public class AOPFactory{
    ?private static Object getClassInstance(String clzName){
    ??Object obj=null;
    ??try{
    ???Class cls=Class.forName(clzName);
    ???obj=(Object)cls.newInstance();
    ??}catch(ClassNotFoundException cnfe){
    ???System.out.println("ClassNotFoundException:"+cnfe.getMessage());
    ??}catch(Exception e){
    ???e.printStackTrace();
    ??}
    ??return obj;
    ?}
    ?
    ?public static Object getAOPProxyedObject(String clzName){
    ??Object proxy=null;
    ??MyHandler handler=new MyHandler();
    ??Object obj=getClassInstance(clzName);
    ??if(obj!=null) {
    ???proxy=handler.bind(obj);
    ??}else{
    ???System.out.println("Can't get the proxyobj");
    ???//throw
    ??}
    ??return proxy;
    ?}
    }

    3)基本的攔截與其工廠我們都實現了,現在測試(ClientTest.java):
    public class ClientTest{
    ?public static void main(String[] args){
    ??StudentInfoService studentInfo=(StudentInfoService)AOPFactory.getAOPProxyedObject("StudentInfoServiceImpl");
    ??studentInfo.findInfo("阿飛");
    ?}
    }
    輸出結果(看你的log4j設置):
    [INFO]調用log日志方法findInfo
    你目前輸入的名字是:阿飛
    ???? 這樣我們需要的效果就出來了,業務處理自己在進行,但是我們實現了日志功能,而業務處理(StudentInfoService)根本不知道存在該行為的。但是Java中提供的動態代理類的實現是針對實現了某些接口的類,如果沒有實現接口的話,不能創建代理類,看以上部分:
    return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
    看到了沒有?obj.getClass().getInterfaces()要求實現了某些接口。以下提供哪些沒有實現接口的實現方案:

    二、子類的實現方案。
    ????? 首先,請上網下CGLib的包,http://sourceforge.net/project/showfiles.php?group_id=56933?。設置好classpath路徑,CGLib與java標準庫提供的實現方案不同,cglib主要是基于實現類(如StudentInfoServiceImpl.java)擴展一個子類來實現。與Dynamic Proxy中的Proxy和InvocationHandler相對應,net.sf.cglib.proxy.Enhancer和MethodInterceptor在CGLib中負責完成代理對象創建和方法截獲處理,產生的是目標類的子類而不是通過接口來實現方法攔截的,Enhancer主要是用于構造動態代理子類來實現攔截,MethodInterceptor(擴展了Callback接口)主要用于實現around advice(AOP中的概念):
    ???? 1)我們的業務處理(StudentInfoServiceImpl.java):
    public class StudentInfoServiceImpl{
    ?public void findInfo(String name){
    ??System.out.println("你目前輸入的名字是:"+name);
    ?}
    }
    ???? 2)實行一個工具來處理日志功能(AOPInstrumenter.java):
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodProxy;
    import java.lang.reflect.Method;
    import org.apache.log4j.Logger;

    public class AOPInstrumenter implements MethodInterceptor{
    ?private Logger log=Logger.getLogger(AOPInstrumenter.class);
    ?private Enhancer enhancer=new Enhancer();
    ?
    ?public Object getInstrumentedClass(Class clz){
    ??enhancer.setSuperclass(clz);
    ??enhancer.setCallback(this);
    ??return enhancer.create();
    ?}
    ?
    ?public Object intercept(Object o,Method method,Object[] args,MethodProxy proxy) throws Throwable{
    ??log.info("調用日志方法"+method.getName());
    ??Object result=proxy.invokeSuper(o,args);
    ??return result;
    ?}
    ?
    }
    ???? 3)我們來測試一下(AOPTest.java):
    public class AOPTest{
    ?public static void main(String[] args){
    ??AOPInstrumenter instrumenter=new AOPInstrumenter();
    ??StudentInfoServiceImpl studentInfo=(StudentInfoServiceImpl)instrumenter.getInstrumentedClass(StudentInfoServiceImpl.class);
    ??studentInfo.findInfo("阿飛");
    ?}
    }
    ?? 輸出結果與以上相同。
    ?CGLib中為實現以上目的,主要提供的類
    1)Enhancer:setCallback(Callback) ,setSuperclass(Class) ,create()返回動態子類Object
    2)MethodInterceptor必須實現的接口:intercept(Object,Method,Object[],MethodProxy)返回的是原方法調用的結果。和Proxy原理一樣。

    三、以上的兩個簡單實現AOP的方案都為你準備好了,你可以自己編寫測試一下,以下簡單介紹一下AOP的基本概念:
    1)aspect(切面):實現了cross-cutting功能,是針對切面的模塊。最常見的是logging模塊,這樣,程序按功能被分為好幾層,如果按傳統的繼承的話,商業模型繼承日志模塊的話根本沒有什么意義,而通過創建一個logging切面就可以使用AOP來實現相同的功能了。
    2)jointpoint(連接點):連接點是切面插入應用程序的地方,該點能被方法調用,而且也會被拋出意外。連接點是應用程序提供給切面插入的地方,可以添加新的方法。比如以上我們的切點可以認為是findInfo(String)方法。
    3)advice(處理邏輯):advice是我們切面功能的實現,它通知程序新的行為。如在logging里,logging advice包括logging的實現代碼,比如像寫日志到一個文件中。advice在jointpoint處插入到應用程序中。以上我們在MyHandler.java中實現了advice的功能
    4)pointcut(切點):pointcut可以控制你把哪些advice應用于jointpoint上去,通常你使用pointcuts通過正則表達式來把明顯的名字和模式進行匹配應用。決定了那個jointpoint會獲得通知。
    5)introduction:允許添加新的方法和屬性到類中。
    6)target(目標類):是指那些將使用advice的類,一般是指獨立的那些商務模型。比如以上的StudentInfoServiceImpl.

    7)proxy(代理類):使用了proxy的模式。是指應用了advice的對象,看起來和target對象很相似。
    8)weaving(插入):是指應用aspects到一個target對象創建proxy對象的過程:complie time,classload time,runtime

    posted @ 2006-06-09 15:33 nbt 閱讀(232) | 評論 (0)編輯 收藏

    Servlet/JSP服務器端的重定向

    通常,在一個設計良好的Web應用中,都會綜合使用Servlet和JSP技術。Servlet控制業務流轉,JSP則負責業務處理結果的顯示。此時,將大量用到重定向技術。

    ??????? 重定向技術可以分為兩類,一類是客戶端重定向,一類是服務器端重定向??蛻舳酥囟ㄏ蚩梢酝ㄟ^設置特定的HTTP頭,或者寫JavaScript腳本實現。本文主要探討服務器端重定向技術的實現。


    服務器端的重定向相關類


    服務器端的重定向技術涉及到javax.servlet.ServletContext、javax.servlet.RequestDispatcher、javax.servlet.http.ServletRequest、javax.servlet.http.ServletResponse等幾個接口。


    服務器端的重定向方式


    服務器端的重定向可以有兩種方式,一是使用HttpServletResponse的sendRedirect()方法,一是使用RequestDispatcher的forward()方法。下面對這兩種方式進行介紹。

    HttpServletResponse.sendRedirect()方法

    HttpServletResponse接口定義了可用于轉向的sendRedirect()方法。代碼如下:

    public void sendRedirect(java.lang.String location)throws java.io.IOException


    這個方法將響應定向到參數location指定的、新的URL。location可以是一個絕對的URL,如response.sendRedirect("http://java.sun.com")也可以使用相對的URL。如果location以“/”開頭,則容器認為相對于當前Web應用的根,否則,容器將解析為相對于當前請求的URL。這種重定向的方法,將導致客戶端瀏覽器的請求URL跳轉。從瀏覽器中的地址欄中可以看到新的URL地址,作用類似于上面設置HTTP響應頭信息的實現。

    RequestDispatcher.forward()方法

    RequestDispatcher是一個Web資源的包裝器,可以用來把當前request傳遞到該資源,或者把新的資源包括到當前響應中。RequestDispatcher接口中定義了兩個方法,參見如下代碼:

    public interface RequestDispatcher {
    void forward(ServletRequest request, ServletResponse response);
    void include(ServletRequest request, ServletResponse response);
    }



    forward()方法將當前的request和response重定向到該RequestDispacher指定的資源。這在實際項目中大量使用,因為完成一個業務操作往往需要跨越多個步驟,每一步驟完成相應的處理后,轉向到下一個步驟。比如,通常業務處理在Servlet中處理,處理的結果轉向到一個JSP頁面進行顯示。這樣看起來類似于Servlet鏈的功能,但是還有一些區別。一個RequestDispatcher對象可以把請求發送到任意一個服務器資源,而不僅僅是另外一個Servlet。 include()方法將把Request Dispatcher資源的輸出包含到當前輸出中。

    注意,只有在尚未向客戶端輸出響應時才可以調用forward()方法,如果頁面緩存不為空,在重定向前將自動清除緩存。否則將拋出一個IllegalStateException異常。


    如何得到RequestDispatcher


    有三種方法可以得到Request Dispatcher對象。

    1.javax.servlet. ServletRequest的getRequestDispatcher(String path)方法,其中path可以是相對路徑,但不能越出當前Servlet上下文。如果path以“/”開頭,則解析為相對于當前上下文的根。

    2.javax.servlet. ServletContext的getRequestDispatcher(String path)方法,其中path必須以“/”開頭,路徑相對于當前的Servlet上下文。可以調用ServletContext的getContext(String uripath)得到另一個Servlet上下文,并可以轉向到外部上下文的一個服務器資源鏈接。

    3.使用javax.servlet. ServletContext的getNamedDispatcher(String name)得到名為name的一個Web資源,包括Servlet和JSP頁面。這個資源的名字在Web應用部署描述文件web.xml中指定。

    這三種方法的使用有細微的差別。比如,下面是一個應用的配置文件web.xml:

    <?xml version="1.0" ?>
    <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
    <web-app>
    <servlet>
    <servlet-name>FirstServlet</servlet-name>
    <servlet-class>org. javaresearch.redirecttest.ServletOne</servlet-class>
    </servlet>
    <servlet>
    <servlet-name>SecondServlet</servlet-name>
    <servlet-class>org.javaresearch. redirecttest.ServletTwo</servlet-class>
    </servlet>
    <servlet-mapping>
    <servlet-name>FirstServlet</servlet-name>
    <url-pattern>/servlet/firstservlet/</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
    <servlet-name>SecondServlet</servlet-name>
    <url-pattern>/servlet/secondservlet/</url-pattern>
    </servlet-mapping>
    </web-app>



    其中定義了兩個Servlet,名字分別為FirstServlet和SecondServlet,對應的類分別為org.javaresearch. redirecttest.ServletOne和org. javaresearch.redirecttest.ServletTwo。可以在瀏覽器中通過類似于下面的鏈接訪問:

    http://localhost:8080/servlet/firstservlet/

    使用1中方法,例如在firstservlet可以寫入下面的代碼:

    RequestDispatcher rd = request.getRequestDispatcher("secondservlet");
    rd.forward(request, response);



    此時控制權將轉向到第二個Servlet了。

    使用2中的方法,可以從Servlet Context中得到RequestDispatcher代碼如下:

    RequestDispatcher rd = getServletContext().getRequest
    Dispatcher("/servlet/secondservlet");
    rd.forward(request, response);



    使用3中的方法,從上面的web. xml配置文件可以看到定義了兩個Servlet,名字分別為FirstServlet和SecondServlet,所以可以得到命名的Dispatcher:

    RequestDispatcher rd = getServletContext().getNamedDispatcher("SecondServlet");
    rd.forward(request, response);



    這樣也可以重定向到SecondServlet了。


    JSP頁面中的重定向


    JSP在解析后編譯為一個Servlet運行,所以在JSP中也可以使用上面的重定向代碼,并且,JSP還提供了更便利的操作,如下:

    <jsp:forward page= "nextpage.jsp"/>



    JSP頁面執行到這兒,將終止當前的處理,將控制權交由nextpage.jsp。


    如何選擇


    RequestDispatcher.forward()方法和HttpServletResponse.sendRedirect()方法的區別是:前者僅是容器中控制權的轉向,在客戶端瀏覽器地址欄中不會顯示出轉向后的地址;后者則是完全的跳轉,瀏覽器將會得到跳轉的地址,并重新發送請求鏈接。這樣,從瀏覽器的地址欄中可以看到跳轉后的鏈接地址。所以,前者更加高效,在前者可以滿足需要時,盡量使用Request Dispatcher.forward()方法,并且,這樣也有助于隱藏實際的鏈接。在有些情況下,比如,需要跳轉到一個其它服務器上的資源,則必須使用HttpServletResponse.sendRequest()方法。

    posted @ 2006-06-09 15:32 nbt 閱讀(210) | 評論 (0)編輯 收藏

    Java知識匯總(二)

    51、垃圾回收的優點和原理。并考慮2種回收機制。
    Java語言中一個顯著的特點就是引入了垃圾回收機制,使c++程序員最頭疼的內存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候不再需要考慮內存管理。由于有個垃圾回收機制,Java中的對象不再有"作用域"的概念,只有對象的引用才有"作用域"。垃圾回收可以有效的防止內存泄露,有效的使用可以使用的內存。垃圾回收器通常是作為一個單獨的低級別的線程運行,不可預知的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清楚和回收,程序員不能實時的調用垃圾回收器對某個對象或所有對象進行垃圾回收。回收機制有分代復制垃圾回收和標記垃圾回收,增量垃圾回收。


    52、請說出你所知道的線程同步的方法。
    wait():使一個線程處于等待狀態,并且釋放所持有的對象的lock。
    sleep():使一個正在運行的線程處于睡眠狀態,是一個靜態方法,調用此方法要捕捉InterruptedException異常。
    notify():喚醒一個處于等待狀態的線程,注意的是在調用此方法的時候,并不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且不是按優先級。
    Allnotity():喚醒所有處入等待狀態的線程,注意并不是給所有喚醒線程一個對象的鎖,而是讓它們競爭。

    53、你所知道的集合類都有哪些?主要方法?
    最常用的集合類是?List?和?Map。?List?的具體實現包括?ArrayList?和?Vector,它們是可變大小的列表,比較適合構建、存儲和操作任何類型對象的元素列表。?List?適用于按數值索引訪問元素的情形。?
    Map?提供了一個更通用的元素存儲方法。?Map?集合類用于存儲元素對(稱作"鍵"和"值"),其中每個鍵映射到一個值。


    54、描述一下JVM加載class文件的原理機制?
    JVM中類的裝載是由ClassLoader和它的子類來實現的,Java?ClassLoader?是一個重要的Java運行時系統組件。它負責在運行時查找和裝入類文件的類。

    55、char型變量中能不能存貯一個中文漢字?為什么??
    能夠定義成為一個中文的,因為java中以unicode編碼,一個char占16個字節,所以放一個中文是沒問題的


    56、多線程有幾種實現方法,都是什么?同步有幾種實現方法,都是什么??
    多線程有兩種實現方法,分別是繼承Thread類與實現Runnable接口?
    同步的實現方面有兩種,分別是synchronized,wait與notify


    58、線程的基本概念、線程的基本狀態以及狀態之間的關系
    線程指在程序執行過程中,能夠執行程序代碼的一個執行單位,每個程序至少都有一個線程,也就是程序本身。
    Java中的線程有四種狀態分別是:運行、就緒、掛起、結束。?


    59、JSP的常用指令
    <%@page?language="java"?contenType="text/html;charset=gb2312"?session="true"?buffer="64kb"?autoFlush="true"?isThreadSafe="true"?info="text"?errorPage="error.jsp"?isErrorPage="true"?isELIgnored="true"?pageEncoding="gb2312"?import="java.sql.*"%>
    isErrorPage(是否能使用Exception對象),isELIgnored(是否忽略表達式)
    <%@include?file="filename"%>
    <%@taglib?prefix="c"uri="http://......"%>


    60、什么情況下調用doGet()和doPost()?
    Jsp頁面中的form標簽里的method屬性為get時調用doGet(),為post時調用doPost()。?

    ?
    61、servlet的生命周期

    web容器加載servlet,生命周期開始。通過調用servlet的init()方法進行servlet的初始化。通過調用service()方法實現,根據請求的不同調用不同的do***()方法。結束服務,web容器調用servlet的destroy()方法。


    62、如何現實servlet的單線程模式
    <%@?page?isThreadSafe="false"%>


    63、頁面間對象傳遞的方法
    request,session,application,cookie等


    64、JSP和Servlet有哪些相同點和不同點,他們之間的聯系是什么??
    JSP是Servlet技術的擴展,本質上是Servlet的簡易方式,更強調應用的外表表達。JSP編譯后是"類servlet"。Servlet和JSP最主要的不同點在于,Servlet的應用邏輯是在Java文件中,并且完全從表示層中的HTML里分離開來。而JSP的情況是Java和HTML可以組合成一個擴展名為.jsp的文件。JSP側重于視圖,Servlet主要用于控制邏輯。


    65、四種會話跟蹤技術
    會話作用域ServletsJSP?頁面描述
    page否是代表與一個頁面相關的對象和屬性。一個頁面由一個編譯好的?Java?servlet?類(可以帶有任何的?include?指令,但是沒有?include?動作)表示。這既包括?servlet?又包括被編譯成?servlet?的?JSP?頁面
    request是是代表與?Web?客戶機發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個?Web?組件(由于?forward?指令和?include?動作的關系)
    session是是代表與用于某個?Web?客戶機的一個用戶體驗相關的對象和屬性。一個?Web?會話可以也經常會跨越多個客戶機請求
    application是是代表與整個?Web?應用程序相關的對象和屬性。這實質上是跨越整個?Web?應用程序,包括多個頁面、請求和會話的一個全局作用域


    66、Request對象的主要方法:
    setAttribute(String?name,Object):設置名字為name的request的參數值
    getAttribute(String?name):返回由name指定的屬性值
    getAttributeNames():返回request對象所有屬性的名字集合,結果是一個枚舉的實例
    getCookies():返回客戶端的所有Cookie對象,結果是一個Cookie數組
    getCharacterEncoding():返回請求中的字符編碼方式
    getContentLength():返回請求的Body的長度
    getHeader(String?name):獲得HTTP協議定義的文件頭信息
    getHeaders(String?name):返回指定名字的request?Header的所有值,結果是一個枚舉的實例
    getHeaderNames():返回所以request?Header的名字,結果是一個枚舉的實例
    getInputStream():返回請求的輸入流,用于獲得請求中的數據
    getMethod():獲得客戶端向服務器端傳送數據的方法
    getParameter(String?name):獲得客戶端傳送給服務器端的有name指定的參數值
    getParameterNames():獲得客戶端傳送給服務器端的所有參數的名字,結果是一個枚舉的實例
    getParameterValues(String?name):獲得有name指定的參數的所有值
    getProtocol():獲取客戶端向服務器端傳送數據所依據的協議名稱
    getQueryString():獲得查詢字符串
    getRequestURI():獲取發出請求字符串的客戶端地址
    getRemoteAddr():獲取客戶端的IP地址
    getRemoteHost():獲取客戶端的名字
    getSession([Boolean?create]):返回和請求相關Session
    getServerName():獲取服務器的名字
    getServletPath():獲取客戶端所請求的腳本文件的路徑
    getServerPort():獲取服務器的端口號
    removeAttribute(String?name):刪除請求中的一個屬性


    67、J2EE是技術還是平臺還是框架?
    ????J2EE本身是一個標準,一個為企業分布式應用的開發提供的標準平臺。
    ????J2EE也是一個框架,包括JDBC、JNDI、RMI、JMS、EJB、JTA等技術。


    68、我們在web應用開發過程中經常遇到輸出某種編碼的字符,如iso8859-1等,如何輸出一個某種編碼的字符串?
    ??Public?String?translate?(String?str)?{
    ????String?tempStr?=?"";
    ????try?{
    ??????tempStr?=?new?String(str.getBytes("ISO-8859-1"),?"GBK");
    ??????tempStr?=?tempStr.trim();
    ????}
    ????catch?(Exception?e)?{
    ??????System.err.println(e.getMessage());
    ????}
    ????return?tempStr;
    ??}


    69、簡述邏輯操作(&,|,^)與條件操作(&&,||)的區別。
    區別主要答兩點:a.條件操作只能操作布爾型的,而邏輯操作不僅可以操作布爾型,而且可以操作數值型
    b.邏輯操作不會產生短路


    70、XML文檔定義有幾種形式?它們之間有何本質區別?解析XML文檔有哪幾種方式??
    a:?兩種形式?dtd??schema,b:?本質區別:schema本身是xml的,可以被XML解析器解析(這也是從DTD上發展schema的根本目的),c:有DOM,SAX,STAX等?
    ????DOM:處理大型文件時其性能下降的非常厲害。這個問題是由DOM的樹結構所造成的,這種結構占用的內存較多,而且DOM必須在解析文件之前把整個文檔裝入內存,適合對XML的隨機訪問
    SAX:不現于DOM,SAX是事件驅動型的XML解析方式。它順序讀取XML文件,不需要一次全部裝載整個文件。當遇到像文件開頭,文檔結束,或者標簽開頭與標簽結束時,它會觸發一個事件,用戶通過在其回調事件中寫入處理代碼來處理XML文件,適合對XML的順序訪問?
    ????STAX:Streaming?API?for?XML?(StAX)


    71、簡述synchronized和java.util.concurrent.locks.Lock的異同??
    主要相同點:Lock能完成synchronized所實現的所有功能
    主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。


    72、EJB的角色和三個對象
    一個完整的基于EJB的分布式計算結構由六個角色組成,這六個角色可以由不同的開發商提供,每個角色所作的工作必須遵循Sun公司提供的EJB規范,以保證彼此之間的兼容性。這六個角色分別是EJB組件開發者(Enterprise?Bean?Provider)?、應用組合者(Application?Assembler)、部署者(Deployer)、EJB?服務器提供者(EJB?Server?Provider)、EJB?容器提供者(EJB?Container?Provider)、系統管理員(System?Administrator)
    三個對象是Remote(Local)接口、Home(LocalHome)接口,Bean類


    73、EJB容器提供的服務
    主要提供聲明周期管理、代碼產生、持續性管理、安全、事務管理、鎖和并發行管理等服務。


    74、EJB規范規定EJB中禁止的操作有哪些??
    ????1.不能操作線程和線程API(線程API指非線程對象的方法如notify,wait等),2.不能操作awt,3.不能實現服務器功能,4.不能對靜態屬生存取,5.不能使用IO操作直接存取文件系統,6.不能加載本地庫.,7.不能將this作為變量和返回,8.不能循環調用。


    75、remote接口和home接口主要作用
    remote接口定義了業務方法,用于EJB客戶端調用業務方法。
    home接口是EJB工廠用于創建和移除查找EJB實例


    76、bean?實例的生命周期
    對于Stateless?Session?Bean、Entity?Bean、Message?Driven?Bean一般存在緩沖池管理,而對于Entity?Bean和Statefull?Session?Bean存在Cache管理,通常包含創建實例,設置上下文、創建EJB?Object(create)、業務方法調用、remove等過程,對于存在緩沖池管理的Bean,在create之后實例并不從內存清除,而是采用緩沖池調度機制不斷重用實例,而對于存在Cache管理的Bean則通過激活和去激活機制保持Bean的狀態并限制內存中實例數量。
    77、EJB的激活機制
    以Stateful?Session?Bean?為例:其Cache大小決定了內存中可以同時存在的Bean實例的數量,根據MRU或NRU算法,實例在激活和去激活狀態之間遷移,激活機制是當客戶端調用某個EJB實例業務方法時,如果對應EJB?Object發現自己沒有綁定對應的Bean實例則從其去激活Bean存儲中(通過序列化機制存儲實例)回復(激活)此實例。狀態變遷前會調用對應的ejbActive和ejbPassivate方法。


    78、EJB的幾種類型
    會話(Session)Bean?,實體(Entity)Bean?消息驅動的(Message?Driven)Bean
    會話Bean又可分為有狀態(Stateful)和無狀態(Stateless)兩種
    實體Bean可分為Bean管理的持續性(BMP)和容器管理的持續性(CMP)兩種


    79、客服端調用EJB對象的幾個基本步驟
    設置JNDI服務工廠以及JNDI服務地址系統屬性,查找Home接口,從Home接口調用Create方法創建Remote接口,通過Remote接口調用其業務方法。


    80、如何給weblogic指定大小的內存??
    在啟動Weblogic的腳本中(位于所在Domian對應服務器目錄下的startServerName),增加set?MEM_ARGS=-Xms32m?-Xmx200m,可以調整最小內存為32M,最大200M
    ?

    81、如何設定的weblogic的熱啟動模式(開發模式)與產品發布模式?
    可以在管理控制臺中修改對應服務器的啟動模式為開發或產品模式之一?;蛘咝薷姆盏膯游募蛘遚ommenv文件,增加set?PRODUCTION_MODE=true。


    82、如何啟動時不需輸入用戶名與密碼?
    修改服務啟動文件,增加?WLS_USER和WLS_PW項。也可以在boot.properties文件中增加加密過的用戶名和密碼.


    83、在weblogic管理制臺中對一個應用域(或者說是一個網站,Domain)進行jms及ejb或連接池等相關信息進行配置后,實際保存在什么文件中?
    保存在此Domain的config.xml文件中,它是服務器的核心配置文件。


    84、說說weblogic中一個Domain的缺省目錄結構?比如要將一個簡單的helloWorld.jsp放入何目錄下,然的在瀏覽器上就可打入http://主機:端口號//helloword.jsp就可以看到運行結果了??又比如這其中用到了一個自己寫的javaBean該如何辦?
    Domain目錄服務器目錄applications,將應用目錄放在此目錄下將可以作為應用訪問,如果是Web應用,應用目錄需要滿足Web應用目錄要求,jsp文件可以直接放在應用目錄中,Javabean需要放在應用目錄的WEB-INF目錄的classes目錄中,設置服務器的缺省應用將可以實現在瀏覽器上無需輸入應用名。


    85、在weblogic中發布ejb需涉及到哪些配置文件
    不同類型的EJB涉及的配置文件不同,都涉及到的配置文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP實體Bean一般還需要weblogic-cmp-rdbms-jar.xml?


    86、如何在weblogic中進行ssl配置與客戶端的認證配置或說說j2ee(標準)進行ssl的配置
    缺省安裝中使用DemoIdentity.jks和DemoTrust.jks??KeyStore實現SSL,需要配置服務器使用Enable?SSL,配置其端口,在產品模式下需要從CA獲取私有密鑰和數字證書,創建identity和trust?keystore,裝載獲得的密鑰和數字證書。可以配置此SSL連接是單向還是雙向的。


    87、如何查看在weblogic中已經發布的EJB?
    可以使用管理控制臺,在它的Deployment中可以查看所有已發布的EJB


    88、CORBA是什么?用途是什么??
    CORBA?標準是公共對象請求代理結構(Common?Object?Request?Broker?Architecture),由對象管理組織?(Object?Management?Group,縮寫為?OMG)標準化。它的組成是接口定義語言(IDL),?語言綁定(binding:也譯為聯編)和允許應用程序間互操作的協議。?其目的為:用不同的程序設計語言書寫在不同的進程中運行,為不同的操作系統開發。


    89、說說你所熟悉或聽說過的j2ee中的幾種常用模式?及對設計模式的一些看法
    ??Session?Facade?Pattern:使用SessionBean訪問EntityBean
    Message?Facade?Pattern:實現異步調用
    EJB?Command?Pattern:使用Command?JavaBeans取代SessionBean,實現輕量級訪問
    Data?Transfer?Object?Factory:通過DTO?Factory簡化EntityBean數據提供特性
    Generic?Attribute?Access:通過AttibuteAccess接口簡化EntityBean數據提供特性
    Business?Interface:通過遠程(本地)接口和Bean類實現相同接口規范業務邏輯一致性
    EJB架構的設計好壞將直接影響系統的性能、可擴展性、可維護性、組件可重用性及開發效率。項目越復雜,項目隊伍越龐大則越能體現良好設計的重要性。


    90、說說在weblogic中開發消息Bean時的persistent與non-persisten的差別
    persistent方式的MDB可以保證消息傳遞的可靠性,也就是如果EJB容器出現問題而JMS服務器依然會將消息在此MDB可用的時候發送過來,而non-persistent方式的消息將被丟棄。


    91、Servlet執行時一般實現哪幾個方法?
    public?void?init(ServletConfig?config)
    public?ServletConfig?getServletConfig()
    public?String?getServletInfo()
    public?void?service(ServletRequest?request,ServletResponse?response)
    public?void?destroy()


    92、j2ee常用的設計模式?說明工廠模式
    ????Java中的23種設計模式:
    Factory(工廠模式),??????Builder(建造模式),???????Factory?Method(工廠方法模式),
    Prototype(原始模型模式),Singleton(單例模式),????Facade(門面模式),
    Adapter(適配器模式),????Bridge(橋梁模式),????????Composite(合成模式),
    Decorator(裝飾模式),????Flyweight(享元模式),?????Proxy(代理模式),
    Command(命令模式),??????Interpreter(解釋器模式),?Visitor(訪問者模式),
    Iterator(迭代子模式),???Mediator(調停者模式),????Memento(備忘錄模式),
    Observer(觀察者模式),???State(狀態模式),?????????Strategy(策略模式),
    Template?Method(模板方法模式),?Chain?Of?Responsibleity(責任鏈模式)
    工廠模式:工廠模式是一種經常被使用到的模式,根據工廠模式實現的類可以根據提供的數據生成一組類中某一個類的實例,通常這一組類有一個公共的抽象父類并且實現了相同的方法,但是這些方法針對不同的數據進行了不同的操作。首先需要定義一個基類,該類的子類通過不同的方法實現了基類中的方法。然后需要定義一個工廠類,工廠類可以根據條件生成不同的子類實例。當得到子類的實例后,開發人員可以調用基類中的方法而不必考慮到底返回的是哪一個子類的實例。


    93、EJB需直接實現它的業務接口或Home接口嗎,請簡述理由。
    遠程接口和Home接口不需要直接實現,他們的實現代碼是由服務器產生的,程序運行中對應實現類會作為對應接口類型的實例被使用。


    94、排序都有哪幾種方法?請列舉。用JAVA實現一個快速排序。
    ????排序的方法有:插入排序(直接插入排序、希爾排序),交換排序(冒泡排序、快速排序),選擇排序(直接選擇排序、堆排序),歸并排序,分配排序(箱排序、基數排序)
    快速排序的偽代碼。
    /?/使用快速排序方法對a[?0?:n-?1?]排序
    從a[?0?:n-?1?]中選擇一個元素作為m?i?d?d?l?e,該元素為支點
    把余下的元素分割為兩段left?和r?i?g?h?t,使得l?e?f?t中的元素都小于等于支點,而right?中的元素都大于等于支點
    遞歸地使用快速排序方法對left?進行排序
    遞歸地使用快速排序方法對right?進行排序
    所得結果為l?e?f?t?+?m?i?d?d?l?e?+?r?i?g?h?t


    95、請對以下在J2EE中常用的名詞進行解釋(或簡單描述)
    web容器:給處于其中的應用程序組件(JSP,SERVLET)提供一個環境,使JSP,SERVLET直接更容器中的環境變量接口交互,不必關注其它系統問題。主要有WEB服務器來實現。例如:TOMCAT,WEBLOGIC,WEBSPHERE等。該容器提供的接口嚴格遵守J2EE規范中的WEB?APPLICATION?標準。我們把遵守以上標準的WEB服務器就叫做J2EE中的WEB容器。
    EJB容器:Enterprise?java?bean?容器。更具有行業領域特色。他提供給運行在其中的組件EJB各種管理功能。只要滿足J2EE規范的EJB放入該容器,馬上就會被容器進行高效率的管理。并且可以通過現成的接口來獲得系統級別的服務。例如郵件服務、事務管理。
    JNDI:(Java?Naming?&?Directory?Interface)JAVA命名目錄服務。主要提供的功能是:提供一個目錄系統,讓其它各地的應用程序在其上面留下自己的索引,從而滿足快速查找和定位分布式應用程序的功能。
    JMS:(Java?Message?Service)JAVA消息服務。主要實現各個應用程序之間的通訊。包括點對點和廣播。
    JTA:(Java?Transaction?API)JAVA事務服務。提供各種分布式事務服務。應用程序只需調用其提供的接口即可。
    JAF:(Java?Action?FrameWork)JAVA安全認證框架。提供一些安全控制方面的框架。讓開發者通過各種部署和自定義實現自己的個性安全控制策略。
    RMI/IIOP:(Remote?Method?Invocation?/internet對象請求中介協議)他們主要用于通過遠程調用服務。例如,遠程有一臺計算機上運行一個程序,它提供股票分析服務,我們可以在本地計算機上實現對其直接調用。當然這是要通過一定的規范才能在異構的系統之間進行通信。RMI是JAVA特有的。


    96、JAVA語言如何進行異常處理,關鍵字:throws,throw,try,catch,finally分別代表什么意義?在try塊中可以拋出異常嗎?
    Java通過面向對象的方法進行異常處理,把各種不同的異常進行分類,并提供了良好的接口。在Java中,每個異常都是一個對象,它是Throwable類或其它子類的實例。當一個方法出現異常后便拋出一個異常對象,該對象中包含有異常信息,調用這個對象的方法可以捕獲到這個異常并進行處理。Java的異常處理是通過5個關鍵詞來實現的:try、catch、throw、throws和finally。一般情況下是用try來執行一段程序,如果出現異常,系統會拋出(throws)一個異常,這時候你可以通過它的類型來捕捉(catch)它,或最后(finally)由缺省處理器來處理。
    用try來指定一塊預防所有"異常"的程序。緊跟在try程序后面,應包含一個catch子句來指定你想要捕捉的"異常"的類型。
    throw語句用來明確地拋出一個"異常"。
    throws用來標明一個成員函數可能拋出的各種"異常"。
    Finally為確保一段代碼不管發生什么"異常"都被執行一段代碼。
    可以在一個成員函數調用的外面寫一個try語句,在這個成員函數內部寫另一個try語句保護其他代碼。每當遇到一個try語句,"異常"的框架就放到堆棧上面,直到所有的try語句都完成。如果下一級的try語句沒有對某種"異常"進行處理,堆棧就會展開,直到遇到有處理這種"異常"的try語句。


    97、一個".java"源文件中是否可以包括多個類(不是內部類)?有什么限制?
    可以。必須只有一個類名與文件名相同。


    98、MVC的各個部分都有那些技術來實現?如何實現??
    MVC是Model-View-Controller的簡寫。"Model"?代表的是應用的業務邏輯(通過JavaBean,EJB組件實現),?"View"?是應用的表示面(由JSP頁面產生),"Controller"?是提供應用的處理過程控制(一般是一個Servlet),通過這種設計模型把應用邏輯,處理過程和顯示邏輯分成不同的組件實現。這些組件可以進行交互和重用。


    99、java中有幾種方法可以實現一個線程?用什么關鍵字修飾同步方法??stop()和suspend()方法為何不推薦使用?
    有兩種實現方法,分別是繼承Thread類與實現Runnable接口
    用synchronized關鍵字修飾同步方法
    反對使用stop(),是因為它不安全。它會解除由線程獲取的所有鎖定,而且如果對象處于一種不連貫狀態,那么其他線程能在那種狀態下檢查和修改它們。結果很難檢查出真正的問題所在。suspend()方法容易發生死鎖。調用suspend()的時候,目標線程會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何線程都不能訪問鎖定的資源,除非被"掛起"的線程恢復運行。對任何線程來說,如果它們想恢復目標線程,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。所以不應該使用suspend(),而應在自己的Thread類中置入一個標志,指出線程應該活動還是掛起。若標志指出線程應該掛起,便用wait()命其進入等待狀態。若標志指出線程應當恢復,則用一個notify()重新啟動線程。


    100、java中有幾種類型的流?JDK為每種類型的流提供了一些抽象類以供繼承,請說出他們分別是哪些類?
    字節流,字符流。字節流繼承于InputStream??OutputStream,字符流繼承于InputStreamReader??OutputStreamWriter。在java.io包中還有許多其他的流,主要是為了提高性能和使用方便。


    ?101、java中會存在內存泄漏嗎,請簡單描述。
    會。如:int?i,i2;??return?(i-i2);???file://when?i為足夠大的正數,i2為足夠大的負數。結果會造成溢位,導致錯誤。


    102、java中實現多態的機制是什么?
    方法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。


    103、垃圾回收器的基本原理是什么?垃圾回收器可以馬上回收內存嗎?有什么辦法主動通知虛擬機進行垃圾回收?
    對于GC來說,當程序員創建對象時,GC就開始監控這個對象的地址、大小以及使用情況。通常,GC采用有向圖的方式記錄和管理堆(heap)中的所有對象。通過這種方式確定哪些對象是"可達的",哪些對象是"不可達的"。當GC確定一些對象為"不可達"時,GC就有責任回收這些內存空間。可以。程序員可以手動執行System.gc(),通知GC運行,但是Java語言規范并不保證GC一定會執行。


    104、靜態變量和實例變量的區別?
    static?i?=?10;?file://常量
    class?A?a;??a.i?=10;//可變


    105、什么是java序列化,如何實現java序列化?
    序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化??梢詫α骰蟮膶ο筮M行讀寫操作,也可將流化后的對象傳輸于網絡之間。序列化是為了解決在對對象流進行讀寫操作時所引發的問題。
    序列化的實現:將需要被序列化的類實現Serializable接口,該接口沒有需要實現的方法,implements?Serializable只是為了標注該對象是可被序列化的,然后使用一個輸出流(如:FileOutputStream)來構造一個ObjectOutputStream(對象流)對象,接著,使用ObjectOutputStream對象的writeObject(Object?obj)方法就可以將參數為obj的對象寫出(即保存其狀態),要恢復的話則用輸入流。


    106、是否可以從一個static方法內部發出對非static方法的調用?
    不可以,如果其中包含對象的method();不能保證對象初始化.


    107、寫clone()方法時,通常都有一行代碼,是什么?
    Clone?有缺省行為,super.clone();他負責產生正確大小的空間,并逐位復制。


    108、在JAVA中,如何跳出當前的多重嵌套循環?
    用break;?return?方法。


    109、List、Map、Set三個接口,存取元素時,各有什么特點?
    List?以特定次序來持有元素,可有重復元素。Set?無法擁有重復元素,內部排序。Map?保存key-value值,value可多值。


    110、J2EE是什么?
    J2EE是Sun公司提出的多層(multi-diered),分布式(distributed),基于組件(component-base)的企業級應用模型(enterpriese?application?model).在這樣的一個應用系統中,可按照功能劃分為不同的組件,這些組件又可在不同計算機上,并且處于相應的層次(tier)中。所屬層次包括客戶層(clietn?tier)組件,web層和組件,Business層和組件,企業信息系統(EIS)層。


    111、UML方面?
    標準建模語言UML。用例圖,靜態圖(包括類圖、對象圖和包圖),行為圖,交互圖(順序圖,合作圖),實現圖。


    112、說出一些常用的類,包,接口,請各舉5個
    常用的類:BufferedReader??BufferedWriter??FileReader??FileWirter??String??Integer
    常用的包:java.lang??java.awt??java.io??java.util??java.sql
    常用的接口:Remote??List??Map??Document??NodeList?


    113、開發中都用到了那些設計模式?用在什么場合??
    每個模式都描述了一個在我們的環境中不斷出現的問題,然后描述了該問題的解決方案的核心。通過這種方式,你可以無數次地使用那些已有的解決方案,無需在重復相同的工作。主要用到了MVC的設計模式。用來開發JSP/Servlet或者J2EE的相關應用。簡單工廠模式等。


    114、jsp有哪些動作?作用分別是什么??
    JSP共有以下6種基本動作?jsp:include:在頁面被請求的時候引入一個文件。?jsp:useBean:尋找或者實例化一個JavaBean。?jsp:setProperty:設置JavaBean的屬性。?jsp:getProperty:輸出某個JavaBean的屬性。?jsp:forward:把請求轉到一個新的頁面。?jsp:plugin:根據瀏覽器類型為Java插件生成OBJECT或EMBED標記。


    115、Anonymous?Inner?Class?(匿名內部類)?是否可以extends(繼承)其它類,是否可以implements(實現)interface(接口)??
    可以繼承其他類或完成其他接口,在swing編程中常用此方式。


    116、應用服務器與WEB?SERVER的區別?
    應用服務器:Weblogic、Tomcat、Jboss
    WEB?SERVER:IIS、?Apache


    117、BS與CS的聯系與區別。
    C/S是Client/Server的縮寫。服務器通常采用高性能的PC、工作站或小型機,并采用大型數據庫系統,如Oracle、Sybase、Informix或?SQL?Server??蛻舳诵枰惭b專用的客戶端軟件。
    B/S是Brower/Server的縮寫,客戶機上只要安裝一個瀏覽器(Browser),如Netscape?Navigator或Internet?Explorer,服務器安裝Oracle、Sybase、Informix或?SQL?Server等數據庫。在這種結構下,用戶界面完全通過WWW瀏覽器實現,一部分事務邏輯在前端實現,但是主要事務邏輯在服務器端實現。瀏覽器通過Web?Server?同數據庫進行數據交互。
    C/S?與?B/S?區別:?
    1.硬件環境不同:?
      C/S?一般建立在專用的網絡上,?小范圍里的網絡環境,?局域網之間再通過專門服務器提供連接和數據交換服務.
      B/S?建立在廣域網之上的,?不必是專門的網絡硬件環境,例與電話上網,?租用設備.?信息自己管理.?有比C/S更強的適應范圍,?一般只要有操作系統和瀏覽器就行?
    2.對安全要求不同?
      C/S?一般面向相對固定的用戶群,?對信息安全的控制能力很強.?一般高度機密的信息系統采用C/S?結構適宜.?可以通過B/S發布部分可公開信息.
      B/S?建立在廣域網之上,?對安全的控制能力相對弱,?可能面向不可知的用戶。
    3.對程序架構不同?
      C/S?程序可以更加注重流程,?可以對權限多層次校驗,?對系統運行速度可以較少考慮.
      B/S?對安全以及訪問速度的多重的考慮,?建立在需要更加優化的基礎之上.?比C/S有更高的要求?B/S結構的程序架構是發展的趨勢,?從MS的.Net系列的BizTalk?2000?Exchange?2000等,?全面支持網絡的構件搭建的系統.?SUN?和IBM推的JavaBean?構件技術等,使?B/S更加成熟.?
    4.軟件重用不同?
      C/S?程序可以不可避免的整體性考慮,?構件的重用性不如在B/S要求下的構件的重用性好.
      B/S?對的多重結構,要求構件相對獨立的功能.?能夠相對較好的重用.就入買來的餐桌可以再利用,而不是做在墻上的石頭桌子?
    5.系統維護不同??
      C/S?程序由于整體性,?必須整體考察,?處理出現的問題以及系統升級.?升級難.?可能是再做一個全新的系統
      B/S?構件組成,方面構件個別的更換,實現系統的無縫升級.?系統維護開銷減到最小.用戶從網上自己下載安裝就可以實現升級.?
    6.處理問題不同?
      C/S?程序可以處理用戶面固定,?并且在相同區域,?安全要求高需求,?與操作系統相關.?應該都是相同的系統
      B/S?建立在廣域網上,?面向不同的用戶群,?分散地域,?這是C/S無法作到的.?與操作系統平臺關系最小.?
    7.用戶接口不同?
      C/S?多是建立的Window平臺上,表現方法有限,對程序員普遍要求較高
      B/S?建立在瀏覽器上,?有更加豐富和生動的表現方式與用戶交流.?并且大部分難度減低,減低開發成本.?
    8.信息流不同?
      C/S?程序一般是典型的中央集權的機械式處理,?交互性相對低
      B/S?信息流向可變化,?B-B?B-C?B-G等信息、流向的變化,?更像交易中心。


    118、LINUX下線程,GDI類的解釋。
    LINUX實現的就是基于核心輕量級進程的"一對一"線程模型,一個線程實體對應一個核心輕量級進程,而線程之間的管理在核外函數庫中實現。?
    GDI類為圖像設備編程接口類庫。


    119、STRUTS的應用(如STRUTS架構)?
    Struts是采用Java?Servlet/JavaServer?Pages技術,開發Web應用程序的開放源碼的framework。?采用Struts能開發出基于MVC(Model-View-Controller)設計模式的應用構架。?Struts有如下的主要功能:?一.包含一個controller?servlet,能將用戶的請求發送到相應的Action對象。?二.JSP自由tag庫,并且在controller?servlet中提供關聯支持,幫助開發員創建交互式表單應用。?三.提供了一系列實用對象:XML處理、通過Java?reflection?APIs自動處理JavaBeans屬性、國際化的提示和消息。


    120、Jdo是什么??
    JDO是Java對象持久化的新的規范,為java?data?object的簡稱,也是一個用于存取某種數據倉庫中的對象的標準化API。JDO提供了透明的對象存儲,因此對開發人員來說,存儲數據對象完全不需要額外的代碼(如JDBC?API的使用)。這些繁瑣的例行工作已經轉移到JDO產品提供商身上,使開發人員解脫出來,從而集中時間和精力在業務邏輯上。另外,JDO很靈活,因為它可以在任何數據底層上運行。JDBC只是面向關系數據庫(RDBMS)JDO更通用,提供到任何數據底層的存儲功能,比如關系數據庫、文件、XML以及對象數據庫(ODBMS)等等,使得應用可移植性更強。

    posted @ 2006-06-09 15:27 nbt 閱讀(508) | 評論 (0)編輯 收藏

    Java知識匯總(一)

    1.面向對象的特征有哪些方面???
    1.抽象:
    抽象就是忽略一個主題中與當前目標無關的那些方面,以便更充分地注意與當前目標有關的方面。抽象并不打算了解全部問題,而只是選擇其中的一部分,暫時不用部分細節。抽象包括兩個方面,一是過程抽象,二是數據抽象。
    2.繼承:
    繼承是一種聯結類的層次模型,并且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。對象的一個新類可以從現有的類中派生,這個過程稱為類繼承。新類繼承了原始類的特性,新類稱為原始類的派生類(子類),而原始類稱為新類的基類(父類)。派生類可以從它的基類那里繼承方法和實例變量,并且類可以修改或增加新的方法使之更適合特殊的需要。
    3.封裝:
    封裝是把過程和數據包圍起來,對數據的訪問只能通過已定義的界面。面向對象計算始于這個基本概念,即現實世界可以被描繪成一系列完全自治、封裝的對象,這些對象通過一個受保護的接口訪問其他對象。
    4.?多態性:
    多態性是指允許不同類的對象對同一消息作出響應。多態性包括參數化多態性和包含多態性。多態性語言具有靈活、抽象、行為共享、代碼共享的優勢,很好的解決了應用程序函數同名問題。


    2、String是最基本的數據類型嗎?
    基本數據類型包括byte、int、char、long、float、double、boolean和short。
    java.lang.String類是final類型的,因此不可以繼承這個類、不能修改這個類。為了提高效率節省空間,我們應該用StringBuffer類


    3、int?和?Integer?有什么區別
    Java?提供兩種不同的類型:引用類型和原始類型(或內置類型)。Int是java的原始數據類型,Integer是java為int提供的封裝類。Java為每個原始類型提供了封裝類。
    原始類型封裝類
    booleanBoolean
    charCharacter
    byteByte
    shortShort
    intInteger
    longLong
    floatFloat
    doubleDouble
    引用類型和原始類型的行為完全不同,并且它們具有不同的語義。引用類型和原始類型具有不同的特征和用法,它們包括:大小和速度問題,這種類型以哪種類型的數據結構存儲,當引用類型和原始類型用作某個類的實例數據時所指定的缺省值。對象引用實例變量的缺省值為?null,而原始類型實例變量的缺省值與它們的類型有關。


    4、String?和StringBuffer的區別
    JAVA平臺提供了兩個類:String和StringBuffer,它們可以儲存和操作字符串,即包含多個字符的字符數據。這個String類提供了數值不可改變的字符串。而這個StringBuffer類提供的字符串進行修改。當你知道字符數據要改變的時候你就可以使用StringBuffer。典型地,你可以使用StringBuffers來動態構造字符數據。


    5、運行時異常與一般異常有何異同?
    異常表示程序運行過程中可能出現的非正常狀態,運行時異常表示虛擬機的通常操作中可能遇到的異常,是一種常見運行錯誤。java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是并不要求必須聲明拋出未被捕獲的運行時異常。


    6、說出Servlet的生命周期,并說出Servlet和CGI的區別。
    Servlet被服務器實例化后,容器運行其init方法,請求到達時運行其service方法,service方法自動派遣運行與請求對應的doXXX方法(doGet,doPost)等,當服務器決定將實例銷毀的時候調用其destroy方法。
    與cgi的區別在于servlet處于服務器進程中,它通過多線程方式運行其service方法,一個實例可以服務于多個請求,并且其實例一般不會銷毀,而CGI對每個請求都產生新的進程,服務完成后就銷毀,所以效率上低于servlet。


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


    8、EJB是基于哪些技術實現的?并說出SessionBean和EntityBean的區別,StatefulBean和StatelessBean的區別。
    ????EJB包括Session?Bean、Entity?Bean、Message?Driven?Bean,基于JNDI、RMI、JAT等技術實現。
    SessionBean在J2EE應用程序中被用來完成一些服務器端的業務操作,例如訪問數據庫、調用其他EJB組件。EntityBean被用來代表應用系統中用到的數據。
    對于客戶機,SessionBean是一種非持久性對象,它實現某些在服務器上運行的業務邏輯。
    對于客戶機,EntityBean是一種持久性對象,它代表一個存儲在持久性存儲器中的實體的對象視圖,或是一個由現有企業應用程序實現的實體。
    Session?Bean?還可以再細分為?Stateful?Session?Bean?與?Stateless?Session?Bean?,這兩種的?Session?Bean都可以將系統邏輯放在?method之中執行,不同的是?Stateful?Session?Bean?可以記錄呼叫者的狀態,因此通常來說,一個使用者會有一個相對應的?Stateful?Session?Bean?的實體。Stateless?Session?Bean?雖然也是邏輯組件,但是他卻不負責記錄使用者狀態,也就是說當使用者呼叫?Stateless?Session?Bean?的時候,EJB?Container?并不會找尋特定的?Stateless?Session?Bean?的實體來執行這個?method。換言之,很可能數個使用者在執行某個?Stateless?Session?Bean?的?methods?時,會是同一個?Bean?的?Instance?在執行。從內存方面來看,?Stateful?Session?Bean?與?Stateless?Session?Bean?比較,?Stateful?Session?Bean?會消耗?J2EE?Server?較多的內存,然而?Stateful?Session?Bean?的優勢卻在于他可以維持使用者的狀態。


    9、Collection?和?Collections的區別。?
      Collection是集合類的上級接口,繼承與他的接口主要有Set?和List.
    Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作。


    10、&和&&的區別。?
    ????&是位運算符,表示按位與運算,&&是邏輯運算符,表示邏輯與(and)。


    11、HashMap和Hashtable的區別。?
    ????HashMap是Hashtable的輕量級實現(非線程安全的實現),他們都完成了Map接口,主要區別在于HashMap允許空(null)鍵值(key),由于非線程安全,效率上可能高于Hashtable。
    HashMap允許將null作為一個entry的key或者value,而Hashtable不允許。
    HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。?
    Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map?interface的一個實現。
    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在多個線程訪問Hashtable時,不需要自己為它的方法實現同步,而HashMap?就必須為之提供外同步。?
    Hashtable和HashMap采用的hash/rehash算法都大概一樣,所以性能不會有很大的差異。


    12、final,?finally,?finalize的區別。?
      final?用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
    finally是異常處理語句結構的一部分,表示總是執行。
    finalize是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉文件等。


    13、sleep()?和?wait()?有什么區別??
    ????sleep是線程類(Thread)的方法,導致此線程暫停執行指定時間,給執行機會給其他線程,但是監控狀態依然保持,到時后會自動恢復。調用sleep不會釋放對象鎖。
    wait是Object類的方法,對此對象調用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態。


    14、Overload和Override的區別。Overloaded的方法是否可以改變返回值的類型?
    方法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫?(Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被"屏蔽"了。如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。


    15、error和exception有什么區別?
    error?表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。
    ????exception?表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。


    16、同步和異步有何異同,在什么情況下分別使用他們?舉例說明。
    如果數據將在線程間共享。例如正在寫的數據以后可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那么這些數據就是共享數據,必須進行同步存取。
    當應用程序在對象上調用了一個需要花費很長時間來執行的方法,并且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率。


    17、abstract?class和interface有什么區別?
    聲明方法的存在而不去實現它的類被叫做抽象類(abstract?class),它用于要創建一個體現某些基本行為的類,并為該類聲明方法,但不能在該類中實現該類的情況。不能創建abstract?類的實例。然而可以創建一個變量,其類型是一個抽象類,并讓它指向具體子類的一個實例。不能有抽象構造函數或抽象靜態方法。Abstract?類的子類為它們父類中的所有抽象方法提供實現,否則它們也是抽象類為。取而代之,在子類中實現該方法。知道其行為的其它類可以在類中實現這些方法。
    接口(interface)是抽象類的變體。在接口中,所有方法都是抽象的。多繼承性可通過實現這樣的接口而獲得。接口中的所有方法都是抽象的,沒有一個有程序體。接口只可以定義static?final成員變量。接口的實現與子類相似,除了該實現類不能從接口定義中繼承行為。當類實現特殊接口時,它定義(即將程序體給予)所有這種接口的方法。然后,它可以在實現了該接口的類的任何對象上調用接口的方法。由于有抽象類,它允許使用接口名作為引用變量的類型。通常的動態聯編將生效。引用可以轉換到接口類型或從接口類型轉換,instanceof?運算符可以用來決定某對象的類是否實現了接口。


    18、heap和stack有什么區別。
    棧是一種線形集合,其添加和刪除元素的操作應在同一段完成。棧按照后進先出的方式進行處理。
    堆是棧的一個組成元素


    19、forward?和redirect的區別
    forward是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,然后把這些內容再發給瀏覽器,瀏覽器根本不知道服務器發送的內容是從哪兒來的,所以它的地址欄中還是原來的地址。
    ????redirect就是服務端根據邏輯,發送一個狀態碼,告訴瀏覽器重新去請求那個地址,一般來說瀏覽器會用剛才請求的所有參數重新請求,所以session,request參數都可以獲取。?


    20、EJB與JAVA?BEAN的區別?
    Java?Bean?是可復用的組件,對Java?Bean并沒有嚴格的規范,理論上講,任何一個Java類都可以是一個Bean。但通常情況下,由于Java?Bean是被容器所創建(如Tomcat)的,所以Java?Bean應具有一個無參的構造器,另外,通常Java?Bean還要實現Serializable接口用于實現Bean的持久性。Java?Bean實際上相當于微軟COM模型中的本地進程內COM組件,它是不能被跨進程訪問的。Enterprise?Java?Bean?相當于DCOM,即分布式組件。它是基于Java的遠程方法調用(RMI)技術的,所以EJB可以被遠程訪問(跨進程、跨計算機)。但EJB必須被布署在諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問真正的EJB組件,而是通過其容器訪問。EJB容器是EJB組件的代理,EJB組件由容器所創建和管理??蛻敉ㄟ^容器來訪問真正的EJB組件。

    21、Static?Nested?Class?和?Inner?Class的不同。
    ????Static?Nested?Class是被聲明為靜態(static)的內部類,它可以不依賴于外部類實例被實例化。而通常的內部類需要在外部類實例化后才能實例化。

    22、JSP中動態INCLUDE與靜態INCLUDE的區別?
    動態INCLUDE用jsp:include動作實現?<jsp:include?page="included.jsp"?flush="true"?/>它總是會檢查所含文件中的變化,適合用于包含動態頁面,并且可以帶參數。
    靜態INCLUDE用include偽碼實現,定不會檢查所含文件的變化,適用于包含靜態頁面<%@?include?file="included.htm"?%>?


    23、什么時候用assert。?
    ????assertion(斷言)在軟件開發中是一種常用的調試方式,很多開發語言中都支持這種機制。在實現中,assertion就是在程序中的一條語句,它對一個boolean表達式進行檢查,一個正確程序必須保證這個boolean表達式的值為true;如果該值為false,說明程序已經處于不正確的狀態下,系統將給出警告或退出。一般來說,assertion用于保證程序最基本、關鍵的正確性。assertion檢查通常在開發和測試時開啟。為了提高性能,在軟件發布后,assertion檢查通常是關閉的。


    24、GC是什么??為什么要有GC??
      GC是垃圾收集的意思(Gabage?Collection),內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java提供的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操作方法。

    ?
    25、short?s1?=?1;?s1?=?s1?+?1;有什么錯??short?s1?=?1;?s1?+=?1;有什么錯??
    ????short?s1?=?1;?s1?=?s1?+?1;?(s1+1運算結果是int型,需要強制轉換類型)
    short?s1?=?1;?s1?+=?1;(可以正確編譯)


    26、Math.round(11.5)等於多少??Math.round(-11.5)等於多少??
    ????Math.round(11.5)==12
    Math.round(-11.5)==-11
    round方法返回與參數最接近的長整數,參數加1/2后求其floor.


    27、String?s?=?new?String("xyz");創建了幾個String?Object??
    ????兩個


    28、設計4個線程,其中兩個線程每次對j增加1,另外兩個線程對j每次減少1。寫出程序。
    以下程序使用內部類實現線程,對j增減的時候沒有考慮順序問題。
    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<100;i++){
    inc();
    }
    }
    ??}
    ??class?Dec?implements?Runnable{
    public?void?run(){
    for(int?i=0;i<100;i++){
    dec();
    }
    ?}
    ??}
    }


    29、Java有沒有goto?
    java中的保留字,現在沒有在java中使用。


    30、啟動一個線程是用run()還是start()?
    啟動一個線程是調用start()方法,使線程所代表的虛擬處理機處于可運行狀態,這意味著它可以由JVM調度并執行。這并不意味著線程就會立即運行。run()方法可以產生必須退出的標志來停止一個線程。


    31、EJB包括(SessionBean,EntityBean)說出他們的生命周期,及如何管理事務的?
    SessionBean:Stateless?Session?Bean?的生命周期是由容器決定的,當客戶機發出請求要建立一個Bean的實例時,EJB容器不一定要創建一個新的Bean的實例供客戶機調用,而是隨便找一個現有的實例提供給客戶機。當客戶機第一次調用一個Stateful?Session?Bean?時,容器必須立即在服務器中創建一個新的Bean實例,并關聯到客戶機上,以后此客戶機調用Stateful?Session?Bean?的方法時容器會把調用分派到與此客戶機相關聯的Bean實例。
    EntityBean:Entity?Beans能存活相對較長的時間,并且狀態是持續的。只要數據庫中的數據存在,Entity?beans就一直存活。而不是按照應用程序或者服務進程來說的。即使EJB容器崩潰了,Entity?beans也是存活的。Entity?Beans生命周期能夠被容器或者?Beans自己管理。
    EJB通過以下技術管理實務:對象管理組織(OMG)的對象實務服務(OTS),Sun?Microsystems的Transaction?Service(JTS)、Java?Transaction?API(JTA),開發組(X/Open)的XA接口。


    32、應用服務器有那些?
    BEA?WebLogic?Server,IBM?WebSphere?Application?Server,Oracle9i?Application?Server,jBoss,Tomcat


    33、給我一個你最常見到的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


    34、接口是否可繼承接口??抽象類是否可實現(implements)接口??抽象類是否可繼承實體類(concrete?class)?
    接口可以繼承接口。抽象類可以實現(implements)接口,抽象類是否可繼承實體類,但前提是實體類必須有明確的構造函數。


    35、List,?Set,?Map是否繼承自Collection接口?
    ????List,Set是,Map不是


    36、說出數據連接池的工作機制是什么?
    J2EE服務器啟動時會建立一定數量的池連接,并一直維持不少于此數目的池連接。客戶端程序需要連接時,池驅動程序會返回一個未使用的池連接并將其表記為忙。如果當前沒有空閑連接,池驅動程序就新建一定數量的連接,新建連接的數量有配置參數決定。當使用的池連接調用完成后,池驅動程序將此連接表記為空閑,其他調用就可以使用這個連接。


    37、abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?
    ????都不能


    38、數組有沒有length()這個方法??String有沒有length()這個方法?
    數組沒有length()這個方法,有length的屬性。String有有length()這個方法。


    39、Set里的元素是不能重復的,那么用什么方法來區分重復與否呢??是用==還是equals()??它們有何區別?
    Set里的元素是不能重復的,那么用iterator()方法來區分重復與否。equals()是判讀兩個Set是否相等。

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


    40、構造器Constructor是否可被override?
    構造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading。
    ?
    ?
    41、是否可以繼承String類?
    String類是final類故不可以繼承。


    42、swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
    switch(expr1)中,expr1是一個整數表達式。因此傳遞給?switch?和?case?語句的參數應該是?int、?short、?char?或者?byte。long,string?都不能作用于swtich。


    43、try?{}里有一個return語句,那么緊跟在這個try后的finally?{}里的code會不會被執行,什么時候被執行,在return前還是后?
    會執行,在return前執行。


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


    45、兩個對象值相同(x.equals(y)?==?true),但卻可有不同的hash?code,這句話對不對?
    不對,有相同的hash?code。


    46、當一個對象被當作參數傳遞到一個方法后,此方法可改變這個對象的屬性,并可返回變化后的結果,那么這里到底是值傳遞還是引用傳遞??
    是值傳遞。Java?編程語言只有值傳遞參數。當一個對象實例作為一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的內容可以在被調用的方法中改變,但對象的引用是永遠不會改變的。


    47、當一個線程進入一個對象的一個synchronized方法后,其它線程是否可進入此對象的其它方法?
    不能,一個對象的一個synchronized方法只能由一個線程訪問。


    48、編程題:?寫一個Singleton出來。
    Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。
    一般Singleton模式通常有幾種種形式:
    第一種形式:?定義一個類,它的構造函數為private的,它有一個static的private的該類變量,在類初始化時實例話,通過一個public的getInstance方法獲取對它的引用,繼而調用其中的方法。
    public?class?Singleton?{
    private?Singleton(){}
      ????file://在自己內部定義自己一個實例,是不是很奇怪?
      ????file://注意這是private?只供內部調用
      ????private?static?Singleton?instance?=?new?Singleton();
      ????file://這里提供了一個供外部訪問本class的靜態方法,可以直接訪問  
      ????public?static?Singleton?getInstance()?{
        ????return?instance;?  
      ????}?
    ????}?
    ????第二種形式:?
    public?class?Singleton?{?
      private?static?Singleton?instance?=?null;
      public?static?synchronized?Singleton?getInstance()?{
      file://這個方法比上面有所改進,不用每次都進行生成對象,只是第一次   ? 
      file://使用時生成實例,提高了效率!
      if?(instance==null)
        instance=new?Singleton();
    return?instance;?  }?
    }?
    其他形式:
    定義一個類,它的構造函數為private的,所有方法為static的。
    一般認為第一種形式要更加安全些?


    49、Java的接口和C++的虛類的相同和不同處。
    由于Java不支持多繼承,而有可能某個類或對象要使用分別在幾個類或對象里面的方法或屬性,現有的單繼承機制就不能滿足要求。與繼承相比,接口有更高的靈活性,因為接口中沒有任何實現代碼。當一個類實現了接口以后,該類要實現接口里面所有的方法和屬性,并且接口里面的屬性在默認狀態下面都是public?static,所有方法默認情況下是public.一個類可以實現多個接口。


    50、Java中的異常處理機制的簡單原理和應用。
    當JAVA程序違反了JAVA的語義規則時,JAVA虛擬機就會將發生的錯誤表示為一個異常。違反語義規則包括2種情況。一種是JAVA類庫內置的語義檢查。例如數組下標越界,會引發IndexOutOfBoundsException;訪問null的對象時會引發NullPointerException。另一種情況就是JAVA允許程序員擴展這種語義檢查,程序員可以創建自己的異常,并自由選擇在何時用throw關鍵字引發異常。所有的異常都是java.lang.Thowable的子類。

    posted @ 2006-06-09 15:21 nbt 閱讀(226) | 評論 (0)編輯 收藏

    玩玩Spring之IOC(一)(轉載)

    ???? Spring的功能是很強大的,在其“絕不發明自己認為好的輪子,而只發明自己認為不好的輪子”的指導思想下,通過充分實踐了“一切實事求是、‘循證架構’的工作方式”的理論,基本上把輕量級的J2EE應用框架(如ORM、MVC等)進行了整合,并構架了一些常用的功能(如DAO),形成了一個功能強大的J2EE輕量級企業應用框架。
      然而,或許是大家對Spring掌握得還不透徹的緣故吧,看到很多軟件企業中用到的Spring功能,基本上大多數都只是用其IOC功能,有時候附帶用了其中的AOP事務管理功能。
      IOC及AOP雖然不是Spring首創,然而其在這兩塊都是做得很不錯的,應該說整個Spring框架就是圍繞著其IOC實現及AOP實現架設起來的。我想,深入挖掘IOC、AOP以及Spring中的實現,使用等,對于初學者幫助會非常大,因此,從本期開始,大峽的《玩玩Spring系列》將伴隨大家一起走進IOC及AOP的世界。
      由于本人水平有限,文中難免有很多不足甚至錯誤之處,還請各位朋友不吝批評指教。
    ?
    一、IOC簡介
      IOC-全稱Inversion?of?Control,中文解釋:控制反轉。另外,IOC又稱DI(全稱)Dependency?Injection,中文解釋:依賴注入。
      呵呵,這些名詞搞得有點像學古文的味道哈。很多大師還都說IOC中有一個著名的好萊塢理論:你呆著別動,到時我會找你。你呆著別動,到時我會找你。由于本人未到過好萊塢參加過社會實踐,因此,這句話理解有點困難。
      IOC是一種新的設計模式,即IOC模式,系統中通過引入實現了IOC模式的IOC容器,即可由IOC容器來管理對象的生命周期、依賴關系等,從而使得應用程序的配置和依賴性規范與實際的應用程序代碼分開。其中一個特點就是通過文本的配件文件進行應用程序組件間相互關系的配置,而不用重新修改并編譯具體的Java代碼。
      當前比較知名的IOC容器有:Pico?Container、Avalon?、Spring、JBoss、HiveMind、EJB等,國內由板橋里人負責的國產開源項目Jdon框架,也是具有IOC容器功能(由于沒來得及認真研讀其源碼,似乎jdon中IOC部份是調用Pico的IOC容器功能來實現的)。
      在上面的幾個IOC容器中,輕量級的有Pico?Container、Avalon、Spring、HiveMind等,超重量級的有EJB,而半輕半重的有容器有JBoss,Jdon等。
      
      IOC究竟是什么?IOC是如何產生的?用在什么場合?為什么我們以前不用IOC,而現在要用IOC?“物有本末,事有終始”,為了更加透徹的理解這一問題,大峽打算從自己所理解的面向對象(OO)設計及編程發展歷程來進行分析,也許這樣能讓IOC的初學者更加了解IOC的發展的前因后果,爭取做到“知其然,知其所以然,使其然!”。
      若大家等不急了,就直接百度一下有關IOC的其它文章,這方面國內很多先驅們已經作了很多介紹。如冰云的《IOC詳解》、板橋里人的設計模式及IOC理論等。
    ?
    二、?最老的OO編程
      記得曾經看《Think?in?Java》最早版本的時候,里面有這么一句讓人振奮話:一切都是對象。這時我們OO編程的核心是圍繞著面向對象編程的三個特性即“繼承”、“封裝”、“多態”來展開的。
    2.1?封裝
      那時我們學會了對現實就的事物及軟件模型進行了抽象。比如要描述一只貓,那么這支貓應該有“顏色”、“重量”、“公母”、“脾氣”、“出生日期”等屬性,另外還有“跑”、“吃”、“叫”、“貓捉老鼠”等方法。如Java代碼來表示,大致就是如下:
    public?Class?Cat
    {
    private?String?color;//顏色
    private?String?weight;//重量
    private?String?sex;//公母
    private?String?temper;//脾氣
    private?String?birthday;//出生日期
    private?void?run?();//跑
    private?void?eat?(Food?food);?//吃(食物)
    private?void?shout(int?type);//叫(類別)
    private?boolean?chase(Mice?mice);//貓捉老鼠
    }
    ?
    2.2?繼承
      最早的OO編程時期,我們還會引入繼承,還經常鼓勵大家多用繼續,認為繼承就是OO編程思想的核心。繼承的核心就是圍繞著如何把類與類之間具有共同特性的部份抽象到基類中。認為這樣不但能使用了OO的特性,還減少了很多子類的代碼。
      我們通過日常生活的常識知道,貓是一種動物,因此動物有的特性他基本上都有。于是,如果我們的系統中不但有貓,還會有很多其它的動物出現。我們就會設計一個動物類,把所有動物的共性抽象到一個基類中。這里,貓及動物基類的代碼大致如下:
    public?abstract?Class?Animal{
    private?String?color;//顏色
    private?String?weight;//重量
    private?String?sex;//公母
    private?String?temper;//脾氣
    private?String?birthday;//出生日期
    private?void?run?();//跑
    private?void?eat?(Food?food);?//吃(食物)
    private?void?shout(int?type);//叫(類別)
    }
    public?Class?Cat?extends?Animal
    ?private?int?power;//能力
    ?private?int?agility;//敏捷度
    ???//??貓捉老鼠是特有的方法
    ?private?boolean?chase(Mice?mice)?{
    ??return?true;
    ?};
    }
    ?
    ?
    2.3?多態
      這時我們還會不時使用到OO的另外一個特性多態。多態是很重要的一門技術,然而很多時候卻沒有很好的理解并使用,回頭看以前的代碼,我們看到有很多地方屬于故弄玄虛的嫌疑。
      接上面的例子,假如我們要寫一個喂養寵物(有貓、狗、豬、豹、老鼠等)的程序。利用Java的多態特性,我們的大致代碼如下:
    public?class?PetManage?{
    ?//喂食我的寵物
    ?public?void?feeding(Animal?a)
    ?{??
    ?}?
    ?/**
    ??*?@param?args
    ??*/
    ?public?static?void?main(String[]?args)?{?
    ??Animal?myPet=new?Cat();
    ??PetManage?pm=new?PetManage();?????
    ??pm.feeding(myPet);
    ?}
    }
      通過使用多態特性,哪一天若我們的不喜歡貓,而是喜歡養豬的時候,只要把new?Cat()變成new?Pig(),即可。
    ?
    2.4?對象生命周期
      這一階段的OO程序中,我們知道要用一個對象的時候,就要使用Java中的關鍵字new來生成一個來用即可。OO對于我們來說,一切都是那么簡單,很多時候甚至感覺OO跟OP的編程方法也沒太大區別。代碼如下:
    Cat?myCat=new?Cat();//創建一支具體的貓
    myCat.shout();//叫一聲
      此時,我們對Java虛擬是非常信任的,我們的思想也很單純,我們知道Java對象的生命開始于new關鍵詞。我們不太關心對象生命的結束,我們知道Java有一個比C語言歷害、智能化的垃圾收集器,他會幫我們自己的清理內存中不用的對象。
      當然,也有的人由于對垃圾收集器忠誠度的懷疑,不放心垃圾收集器的能力,于是在程序中經常要加一句類似“myPet=null”的代碼來結束對象的生命。
      當然,我們也知道有一些外部資源如數據庫連接等,需要手動熟悉資源。于是知道在使用類似資源的時候必須都加上一句:conn.close(),有時候還要在close()后面再加一句:conn=null。呵呵,非常有意思。
    ?
    2.5小結
      現在看來,其實那時確實犯了很多幼稚的錯誤,也走了不少的彎路,做了很多畫蛇添足的工作,寫了很多難與維護的代碼。
      對比今天的IOC模式,若要從早的OO方法中硬要找一個類似Spring的容器的話,那就是:“程序員+JVM本身”。是程序員以及JVM一起我們管理對象的生命周期、對象之間的關系等。那時候若有任何變動都需要改代碼,(雖然好的設計代碼修改會非常少,但也得改?。?,然后編譯,然后拿到測試環境及用戶環境中執行。如此反復,年日復一日、年復一年。
      那時我們的代碼復用用得最多的就是OO的繼承功能,另外還有很多OP方法中帶過來的函數。
      本文中涉及到的幾個簡單源碼,請到EasyJF開源團隊官網下載,地址:
      http://www.easyjf.com/html/bbs/20060602/12718636-1843943.htm?ejid=1287314863003738
    ?
      

    posted @ 2006-06-09 11:57 nbt 閱讀(210) | 評論 (0)編輯 收藏

    僅列出標題
    共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    導航

    統計

    常用鏈接

    留言簿(3)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    相冊

    收藏夾

    Java技術網站

    友情鏈接

    國內一些開源網站

    最新隨筆

    搜索

    積分與排名

    最新評論

    閱讀排行榜

    評論排行榜

    主站蜘蛛池模板: 国产91成人精品亚洲精品| 亚洲国产精品va在线播放| 成全高清视频免费观看| 国产91色综合久久免费| 最近中文字幕大全中文字幕免费| 免费人成在线观看网站| 久久久免费的精品| 无码国产精品一区二区免费3p | 国产精品亚洲高清一区二区| 又粗又大又猛又爽免费视频 | 国产精品免费无遮挡无码永久视频| a毛片久久免费观看| 国产麻豆一精品一AV一免费| 99热在线免费观看| 57pao一国产成永久免费| 欧洲乱码伦视频免费| 成年人网站在线免费观看| 日本无卡码免费一区二区三区| 免费大香伊蕉在人线国产| 亚洲精品网站在线观看不卡无广告 | 国产午夜精品理论片免费观看| 国产午夜无码精品免费看动漫| 日韩av无码久久精品免费| 中文字幕乱码免费视频| 成人男女网18免费视频| 免费在线视频一区| 中文字幕亚洲乱码熟女一区二区| 久久国产精品亚洲综合| 亚洲综合久久久久久中文字幕| 亚洲一卡2卡3卡4卡乱码 在线| 亚洲乱亚洲乱妇无码| 一级黄色免费大片| 无码日韩精品一区二区三区免费| 台湾一级毛片永久免费| 国产男女猛烈无遮挡免费视频| 国产成人A亚洲精V品无码| 亚洲欧洲久久精品| 成人婷婷网色偷偷亚洲男人的天堂| 国产免费伦精品一区二区三区| 99久久国产免费中文无字幕| 成人免费无遮挡无码黄漫视频|