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

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

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

    隨筆-61  評論-13  文章-19  trackbacks-0
      2006年3月14日
         摘要:   閱讀全文
    posted @ 2010-02-04 15:30 xnabx 閱讀(1613) | 評論 (1)編輯 收藏
         摘要:   閱讀全文
    posted @ 2010-01-25 11:10 xnabx 閱讀(1029) | 評論 (1)編輯 收藏
         摘要:   閱讀全文
    posted @ 2010-01-21 09:52 xnabx 閱讀(1724) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2010-01-15 10:10 xnabx 閱讀(1407) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2010-01-15 09:57 xnabx 閱讀(336) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2009-12-04 11:45 xnabx 閱讀(605) | 評論 (3)編輯 收藏
         摘要:   閱讀全文
    posted @ 2009-12-03 15:26 xnabx 閱讀(312) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2009-12-01 16:02 xnabx 閱讀(186) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2009-12-01 11:05 xnabx 閱讀(321) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2009-11-10 09:05 xnabx 閱讀(759) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2009-03-18 14:06 xnabx 閱讀(149) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2008-10-29 16:34 xnabx 閱讀(112) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2008-07-30 15:18 xnabx 閱讀(239) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2008-07-23 11:20 xnabx 閱讀(387) | 評論 (0)編輯 收藏
    出處:http://m.tkk7.com/xmatthew/archive/2008/04/14/192450.html
    (轉(zhuǎn))設(shè)計一個Tomcat訪問日志分析工具
    常使用web服務(wù)器的朋友大都了解,一般的web server有兩部分日志:
        一是運(yùn)行中的日志,它主要記錄運(yùn)行的一些信息,尤其是一些異常錯誤日志信息
        二是訪問日志信息,它記錄的訪問的時間,IP,訪問的資料等相關(guān)信息。
       
    現(xiàn)在我來和大家介紹一下利用tomcat產(chǎn)生的訪問日志數(shù)據(jù),我們能做哪些有效的分析數(shù)據(jù)?

    首先是配置tomcat訪問日志數(shù)據(jù),默認(rèn)情況下訪問日志沒有打開,配置的方式如下:
        編輯 ${catalina}/conf/server.xml文件.注:${catalina}是tomcat的安裝目錄
        把以下的注釋(<!-- -->)去掉即可。
                <!--
            <Valve className="org.apache.catalina.valves.AccessLogValve"
                     directory="logs"  prefix="localhost_access_log." suffix=".txt"
                     pattern="common" resolveHosts="false"/>
            -->
        其中 directory是產(chǎn)生的目錄 tomcat安裝${catalina}作為當(dāng)前目錄
        pattern表示日志生產(chǎn)的格式,common是tomcat提供的一個標(biāo)準(zhǔn)設(shè)置格式。其具體的表達(dá)式為 %h %l %u %t "%r" %s %b
        但本人建議采用以下具體的配置,因為標(biāo)準(zhǔn)配置有一些重要的日志數(shù)據(jù)無法生。
            %h %l %u %t "%r" %s %b %T 
    具體的日志產(chǎn)生樣式說明如下(從官方文檔中摘錄):
        * %a - Remote IP address
        * %A - Local IP address
        * %b - Bytes sent, excluding HTTP headers, or '-' if zero
        * %B - Bytes sent, excluding HTTP headers
        * %h - Remote host name (or IP address if resolveHosts is false)
        * %H - Request protocol
        * %l - Remote logical username from identd (always returns '-')
        * %m - Request method (GET, POST, etc.)
        * %p - Local port on which this request was received
        * %q - Query string (prepended with a '?' if it exists)
        * %r - First line of the request (method and request URI)
        * %s - HTTP status code of the response
        * %S - User session ID
        * %t - Date and time, in Common Log Format
        * %u - Remote user that was authenticated (if any), else '-'
        * %U - Requested URL path
        * %v - Local server name
        * %D - Time taken to process the request, in millis
        * %T - Time taken to process the request, in seconds

    There is also support to write information from the cookie, incoming header, the Session or something else in the ServletRequest. It is modeled after the apache syntax:

        * %{xxx}i for incoming headers
        * %{xxx}c for a specific cookie
        * %{xxx}r xxx is an attribute in the ServletRequest
        * %{xxx}s xxx is an attribute in the HttpSession


    現(xiàn)在我們回頭再來看一下下面這個配置 %h %l %u %t "%r" %s %b %T 生產(chǎn)的訪問日志數(shù)據(jù),我們可以做哪些事?
    先看一下,我們能得到的數(shù)據(jù)有:
        * %h 訪問的用戶IP地址
        * %l 訪問邏輯用戶名,通常返回'-'
        * %u 訪問驗證用戶名,通常返回'-'
        * %t 訪問日時
        * %r 訪問的方式(post或者是get),訪問的資源和使用的http協(xié)議版本
        * %s 訪問返回的http狀態(tài)
        * %b 訪問資源返回的流量
        * %T 訪問所使用的時間
       
    有了這些數(shù)據(jù),我們可以根據(jù)時間段做以下的分析處理(圖片使用jfreechart工具動態(tài)生成):
      * 獨(dú)立IP數(shù)統(tǒng)計
      * 訪問請求數(shù)統(tǒng)計
      * 訪問資料文件數(shù)統(tǒng)計
      * 訪問流量統(tǒng)計
      * 訪問處理響應(yīng)時間統(tǒng)計
      * 統(tǒng)計所有404錯誤頁面
      * 統(tǒng)計所有500錯誤的頁面
      * 統(tǒng)計訪問最頻繁頁面
      * 統(tǒng)計訪問處理時間最久頁面
      * 統(tǒng)計并發(fā)訪問頻率最高的頁面



























    分析工具包括兩大部分,一個是后臺解釋程序,每天執(zhí)行一次對后臺日志數(shù)據(jù)進(jìn)行解析后保存到數(shù)據(jù)庫中。
    第二個是顯示程序,從數(shù)據(jù)庫中查詢數(shù)據(jù)并生成相應(yīng)的圖表信息。
    posted @ 2008-04-15 12:06 xnabx 閱讀(560) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2008-04-09 08:50 xnabx 閱讀(36) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2008-03-19 13:00 xnabx 閱讀(187) | 評論 (0)編輯 收藏

    如果你覺得你的Eclipse在啟動的時候很慢(比如說超過20秒鐘),也許你要調(diào)整一下你的Eclipse啟動參數(shù)了,以下是一些``小貼士'':

    1. 檢查啟動Eclipse的JVM設(shè)置。 在Help\About Eclipse SDK\Configuration Detail里面,你可以看到啟動Eclipse的JVM。 這個JVM和你在Eclipse中設(shè)置的Installed JDK是兩回事情。 如果啟動Eclipse的JVM還是JDK 1.4的話,那最好改為JDK 5,因為JDK 5的性能比1.4更好。

    C:\eclipse\eclipse.exe -vm "C:\Program Files\Java\jdk1.5.0_08\ bin\javaw.exe"

    2. 檢查Eclipse所使用的heap的大小。 在C:\eclipse目錄下有一個配置文件eclipse.ini,其中配置了Eclipse啟動的默認(rèn)heap大小

    -vmargs
    -Xms40M
    -Xmx256M

    所以你可以把默認(rèn)值改為:

    -vmargs
    -Xms256M
    -Xmx512M

    當(dāng)然,也可以這樣做,把堆的大小改為256 - 512。

    C:\eclipse\eclipse.exe -vm "C:\Program Files\Java\jdk1.5.0_08\ bin\javaw.exe" -vmargs -Xms256M -Xmx512M

    3. 其他的啟動參數(shù)。 如果你有一個雙核的CPU,也許可以嘗試這個參數(shù):

    -XX:+UseParallelGC

    讓GC可以更快的執(zhí)行。(只是JDK 5里對GC新增加的參數(shù))

    posted @ 2007-12-25 10:55 xnabx 閱讀(487) | 評論 (0)編輯 收藏
     

    Java對多線程的支持與同步機(jī)制深受大家的喜愛,似乎看起來使用了synchronized關(guān)鍵字就可以輕松地解決多線程共享數(shù)據(jù)同步問題。到底如何?――還得對synchronized關(guān)鍵字的作用進(jìn)行深入了解才可定論。

    總的說來,synchronized關(guān)鍵字可以作為函數(shù)的修飾符,也可作為函數(shù)內(nèi)的語句,也就是平時說的同步方法和同步語句塊。如果再細(xì)的分類,synchronized可作用于instance變量、object reference(對象引用)、static函數(shù)和class literals(類名稱字面常量)身上。

    在進(jìn)一步闡述之前,我們需要明確幾點:

    A.無論synchronized關(guān)鍵字加在方法上還是對象上,它取得的鎖都是對象,而不是把一段代碼或函數(shù)當(dāng)作鎖――而且同步方法很可能還會被其他線程的對象訪問。

    B.每個對象只有一個鎖(lock)與之相關(guān)聯(lián)。

    C.實現(xiàn)同步是要很大的系統(tǒng)開銷作為代價的,甚至可能造成死鎖,所以盡量避免無謂的同步控制。

    接著來討論synchronized用到不同地方對代碼產(chǎn)生的影響:

    假設(shè)P1P2是同一個類的不同對象,這個類中定義了以下幾種情況的同步塊或同步方法,P1P2就都可以調(diào)用它們。

    1. synchronized當(dāng)作函數(shù)修飾符時,示例代碼如下:

    Public synchronized void methodAAA()

    {

    //….

    }

    這也就是同步方法,那這時synchronized鎖定的是哪個對象呢?它鎖定的是調(diào)用這個同步方法對象。也就是說,當(dāng)一個對象P1在不同的線程中執(zhí)行這個同步方法時,它們之間會形成互斥,達(dá)到同步的效果。但是這個對象所屬的Class所產(chǎn)生的另一對象P2卻可以任意調(diào)用這個被加了synchronized關(guān)鍵字的方法。

    上邊的示例代碼等同于如下代碼:

    public void methodAAA()

    {

    synchronized (this)      // (1)

    {

           //…..

    }

    }

     (1)處的this指的是什么呢?它指的就是調(diào)用這個方法的對象,如P1。可見同步方法實質(zhì)是將synchronized作用于object reference。――那個拿到了P1對象鎖的線程,才可以調(diào)用P1的同步方法,而對P2而言,P1這個鎖與它毫不相干,程序也可能在這種情形下擺脫同步機(jī)制的控制,造成數(shù)據(jù)混亂:(

    2.同步塊,示例代碼如下:

               public void method3(SomeObject so)

                  {

                         synchronized(so)

    {

           //…..

    }

    }

    這時,鎖就是so這個對象,誰拿到這個鎖誰就可以運(yùn)行它所控制的那段代碼。當(dāng)有一個明確的對象作為鎖時,就可以這樣寫程序,但當(dāng)沒有明確的對象作為鎖,只是想讓一段代碼同步時,可以創(chuàng)建一個特殊的instance變量(它得是一個對象)來充當(dāng)鎖:

    class Foo implements Runnable

    {

           private byte[] lock = new byte[0]; // 特殊的instance變量

        Public void methodA()

    {

           synchronized(lock) { //… }

    }

    //…..

    }

    注:零長度的byte數(shù)組對象創(chuàng)建起來將比任何對象都經(jīng)濟(jì)――查看編譯后的字節(jié)碼:生成零長度的byte[]對象只需3條操作碼,而Object lock = new Object()則需要7行操作碼。

    3.將synchronized作用于static 函數(shù),示例代碼如下:

          Class Foo

    {

    public synchronized static void methodAAA()   // 同步的static 函數(shù)

    {

    //….

    }

    public void methodBBB()

    {

           synchronized(Foo.class)   // class literal(類名稱字面常量)

    }

           }

       代碼中的methodBBB()方法是把class literal作為鎖的情況,它和同步的static函數(shù)產(chǎn)生的效果是一樣的,取得的鎖很特別,是當(dāng)前調(diào)用這個方法的對象所屬的類(Class,而不再是由這個Class產(chǎn)生的某個具體對象了)。

    記得在《Effective Java》一書中看到過將 Foo.class P1.getClass()用于作同步鎖還不一樣,不能用P1.getClass()來達(dá)到鎖這個Class的目的。P1指的是由Foo類產(chǎn)生的對象。

    可以推斷:如果一個類中定義了一個synchronizedstatic函數(shù)A,也定義了一個synchronized instance函數(shù)B,那么這個類的同一對象Obj在多線程中分別訪問AB兩個方法時,不會構(gòu)成同步,因為它們的鎖都不一樣。A方法的鎖是Obj這個對象,而B的鎖是Obj所屬的那個Class

    小結(jié)如下:

    搞清楚synchronized鎖定的是哪個對象,就能幫助我們設(shè)計更安全的多線程程序。

     

    還有一些技巧可以讓我們對共享資源的同步訪問更加安全:

    1. 定義private instance變量+它的 get方法,而不要定義public/protectedinstance變量。如果將變量定義為public,對象在外界可以繞過同步方法的控制而直接取得它,并改動它。這也是JavaBean的標(biāo)準(zhǔn)實現(xiàn)方式之一。

    2. 如果instance變量是一個對象,如數(shù)組或ArrayList什么的,那上述方法仍然不安全,因為當(dāng)外界對象通過get方法拿到這個instance對象的引用后,又將其指向另一個對象,那么這個private變量也就變了,豈不是很危險。這個時候就需要將get方法也加上synchronized同步,并且,只返回這個private對象的clone()――這樣,調(diào)用端得到的就是對象副本的引用了。


    posted @ 2007-10-11 14:19 xnabx 閱讀(265) | 評論 (0)編輯 收藏
         摘要:   閱讀全文
    posted @ 2007-07-29 09:17 xnabx 閱讀(388) | 評論 (0)編輯 收藏

    這幾個學(xué)習(xí)材料非常短小精悍,可清晰快捷的掌握以下幾個概念,方便更深入學(xué)習(xí) 

    XML tutorial:

    http://www.w3schools.com/xml/default.asp

     

    SOAP tutorial:

    http://www.w3schools.com/soap/default.asp

     

    WSDL tutorial:

    http://www.w3schools.com/wsdl/default.asp

     

    WEB Service tutorial:

    http://www.w3schools.com/webservices/default.asp

    posted @ 2007-07-13 09:00 xnabx 閱讀(175) | 評論 (0)編輯 收藏


    類-->對象-->實例

    人類是類
    某個人是對象
    你是實例
    實例本身也是對象。

    表現(xiàn)出來是這樣的
    String 類
    String str   str是對象
    String str = "abc";  "abc"是實例,也是對象.
    這樣也能解釋instance of object這種說法  str的實例是"abc"
    posted @ 2007-07-05 08:47 xnabx 閱讀(430) | 評論 (1)編輯 收藏
    1.?概述?

    本文主要包括以下幾個方面:編碼基本知識,java,系統(tǒng)軟件,url,工具軟件等。?

    在下面的描述中,將以"中文"兩個字為例,經(jīng)查表可以知道其GB2312編碼是"d6d0?cec4",Unicode編碼為"4e2d?6587",UTF編碼就是"e4b8ad?e69687"。注意,這兩個字沒有iso8859-1編碼,但可以用iso8859-1編碼來"表示"。?

    2.?編碼基本知識?

    最早的編碼是iso8859-1,和ascii編碼相似。但為了方便表示各種各樣的語言,逐漸出現(xiàn)了很多標(biāo)準(zhǔn)編碼,重要的有如下幾個。?

    2.1.?iso8859-1?

    屬于單字節(jié)編碼,最多能表示的字符范圍是0-255,應(yīng)用于英文系列。比如,字母'a'的編碼為0x61=97。?

    很明顯,iso8859-1編碼表示的字符范圍很窄,無法表示中文字符。但是,由于是單字節(jié)編碼,和計算機(jī)最基礎(chǔ)的表示單位一致,所以很多時候,仍舊使用iso8859-1編碼來表示。而且在很多協(xié)議上,默認(rèn)使用該編碼。比如,雖然"中文"兩個字不存在iso8859-1編碼,以gb2312編碼為例,應(yīng)該是"d6d0?cec4"兩個字符,使用iso8859-1編碼的時候則將它拆開為4個字節(jié)來表示:"d6?d0?ce?c4"(事實上,在進(jìn)行存儲的時候,也是以字節(jié)為單位處理的)。而如果是UTF編碼,則是6個字節(jié)"e4?b8?ad?e6?96?87"。很明顯,這種表示方法還需要以另一種編碼為基礎(chǔ)。?

    2.2.?GB2312/GBK?

    這就是漢子的國標(biāo)碼,專門用來表示漢字,是雙字節(jié)編碼,而英文字母和iso8859-1一致(兼容iso8859-1編碼)。其中g(shù)bk編碼能夠用來同時表示繁體字和簡體字,而gb2312只能表示簡體字,gbk是兼容gb2312編碼的。?

    2.3.?unicode?

    這是最統(tǒng)一的編碼,可以用來表示所有語言的字符,而且是定長雙字節(jié)(也有四字節(jié)的)編碼,包括英文字母在內(nèi)。所以可以說它是不兼容iso8859-1編碼的,也不兼容任何編碼。不過,相對于iso8859-1編碼來說,uniocode編碼只是在前面增加了一個0字節(jié),比如字母'a'為"00?61"。?

    需要說明的是,定長編碼便于計算機(jī)處理(注意GB2312/GBK不是定長編碼),而unicode又可以用來表示所有字符,所以在很多軟件內(nèi)部是使用unicode編碼來處理的,比如java。?

    2.4.?UTF?

    考慮到unicode編碼不兼容iso8859-1編碼,而且容易占用更多的空間:因為對于英文字母,unicode也需要兩個字節(jié)來表示。所以unicode不便于傳輸和存儲。因此而產(chǎn)生了utf編碼,utf編碼兼容iso8859-1編碼,同時也可以用來表示所有語言的字符,不過,utf編碼是不定長編碼,每一個字符的長度從1-6個字節(jié)不等。另外,utf編碼自帶簡單的校驗功能。一般來講,英文字母都是用一個字節(jié)表示,而漢字使用三個字節(jié)。?

    注意,雖然說utf是為了使用更少的空間而使用的,但那只是相對于unicode編碼來說,如果已經(jīng)知道是漢字,則使用GB2312/GBK無疑是最節(jié)省的。不過另一方面,值得說明的是,雖然utf編碼對漢字使用3個字節(jié),但即使對于漢字網(wǎng)頁,utf編碼也會比unicode編碼節(jié)省,因為網(wǎng)頁中包含了很多的英文字符。?

    3.?java對字符的處理?

    在java應(yīng)用軟件中,會有多處涉及到字符集編碼,有些地方需要進(jìn)行正確的設(shè)置,有些地方需要進(jìn)行一定程度的處理。?

    3.1.?getBytes(charset)?

    這是java字符串處理的一個標(biāo)準(zhǔn)函數(shù),其作用是將字符串所表示的字符按照charset編碼,并以字節(jié)方式表示。注意字符串在java內(nèi)存中總是按unicode編碼存儲的。比如"中文",正常情況下(即沒有錯誤的時候)存儲為"4e2d?6587",如果charset為"gbk",則被編碼為"d6d0?cec4",然后返回字節(jié)"d6?d0?ce?c4"。如果charset為"utf8"則最后是"e4?b8?ad?e6?96?87"。如果是"iso8859-1",則由于無法編碼,最后返回?"3f?3f"(兩個問號)。?

    3.2.?new?String(charset)?

    這是java字符串處理的另一個標(biāo)準(zhǔn)函數(shù),和上一個函數(shù)的作用相反,將字節(jié)數(shù)組按照charset編碼進(jìn)行組合識別,最后轉(zhuǎn)換為unicode存儲。參考上述getBytes的例子,"gbk"?和"utf8"都可以得出正確的結(jié)果"4e2d?6587",但iso8859-1最后變成了"003f?003f"(兩個問號)。?

    因為utf8可以用來表示/編碼所有字符,所以new?String(?str.getBytes(?"utf8"?),?"utf8"?)?===?str,即完全可逆。?

    3.3.?setCharacterEncoding()?

    該函數(shù)用來設(shè)置http請求或者相應(yīng)的編碼。?

    對于request,是指提交內(nèi)容的編碼,指定后可以通過getParameter()則直接獲得正確的字符串,如果不指定,則默認(rèn)使用iso8859-1編碼,需要進(jìn)一步處理。參見下述"表單輸入"。值得注意的是在執(zhí)行setCharacterEncoding()之前,不能執(zhí)行任何getParameter()。java?doc上說明:This?method?must?be?called?prior?to?reading?request?parameters?or?reading?input?using?getReader()。而且,該指定只對POST方法有效,對GET方法無效。分析原因,應(yīng)該是在執(zhí)行第一個getParameter()的時候,java將會按照編碼分析所有的提交內(nèi)容,而后續(xù)的getParameter()不再進(jìn)行分析,所以setCharacterEncoding()無效。而對于GET方法提交表單是,提交的內(nèi)容在URL中,一開始就已經(jīng)按照編碼分析所有的提交內(nèi)容,setCharacterEncoding()自然就無效。?

    對于response,則是指定輸出內(nèi)容的編碼,同時,該設(shè)置會傳遞給瀏覽器,告訴瀏覽器輸出內(nèi)容所采用的編碼。?

    3.4.?處理過程?

    下面分析兩個有代表性的例子,說明java對編碼有關(guān)問題的處理方法。?

    3.4.1.?表單輸入?

    User?input??*(gbk:d6d0?cec4)??browser??*(gbk:d6d0?cec4)??web?server??iso8859-1(00d6?00d?000ce?00c4)??class,需要在class中進(jìn)行處理:getbytes("iso8859-1")為d6?d0?ce?c4,new?String("gbk")為d6d0?cec4,內(nèi)存中以unicode編碼則為4e2d?6587。?

    l?用戶輸入的編碼方式和頁面指定的編碼有關(guān),也和用戶的操作系統(tǒng)有關(guān),所以是不確定的,上例以gbk為例。?

    l?從browser到web?server,可以在表單中指定提交內(nèi)容時使用的字符集,否則會使用頁面指定的編碼。而如果在url中直接用?的方式輸入?yún)?shù),則其編碼往往是操作系統(tǒng)本身的編碼,因為這時和頁面無關(guān)。上述仍舊以gbk編碼為例。?

    l?Web?server接收到的是字節(jié)流,默認(rèn)時(getParameter)會以iso8859-1編碼處理之,結(jié)果是不正確的,所以需要進(jìn)行處理。但如果預(yù)先設(shè)置了編碼(通過request.?setCharacterEncoding?()),則能夠直接獲取到正確的結(jié)果。?

    l?在頁面中指定編碼是個好習(xí)慣,否則可能失去控制,無法指定正確的編碼。?

    3.4.2.?文件編譯?

    假設(shè)文件是gbk編碼保存的,而編譯有兩種編碼選擇:gbk或者iso8859-1,前者是中文windows的默認(rèn)編碼,后者是linux的默認(rèn)編碼,當(dāng)然也可以在編譯時指定編碼。?

    Jsp??*(gbk:d6d0?cec4)??java?file??*(gbk:d6d0?cec4)??compiler?read??uincode(gbk:?4e2d?6587;?iso8859-1:?00d6?00d?000ce?00c4)??compiler?write??utf(gbk:?e4b8ad?e69687;?iso8859-1:?*)??compiled?file??unicode(gbk:?4e2d?6587;?iso8859-1:?00d6?00d?000ce?00c4)??class。所以用gbk編碼保存,而用iso8859-1編譯的結(jié)果是不正確的。?

    class??unicode(4e2d?6587)??system.out?/?jsp.out??gbk(d6d0?cec4)??os?console?/?browser。?

    l?文件可以以多種編碼方式保存,中文windows下,默認(rèn)為ansi/gbk。?

    l?編譯器讀取文件時,需要得到文件的編碼,如果未指定,則使用系統(tǒng)默認(rèn)編碼。一般class文件,是以系統(tǒng)默認(rèn)編碼保存的,所以編譯不會出問題,但對于jsp文件,如果在中文windows下編輯保存,而部署在英文linux下運(yùn)行/編譯,則會出現(xiàn)問題。所以需要在jsp文件中用pageEncoding指定編碼。?

    l?Java編譯的時候會轉(zhuǎn)換成統(tǒng)一的unicode編碼處理,最后保存的時候再轉(zhuǎn)換為utf編碼。?

    l?當(dāng)系統(tǒng)輸出字符的時候,會按指定編碼輸出,對于中文windows下,System.out將使用gbk編碼,而對于response(瀏覽器),則使用jsp文件頭指定的contentType,或者可以直接為response指定編碼。同時,會告訴browser網(wǎng)頁的編碼。如果未指定,則會使用iso8859-1編碼。對于中文,應(yīng)該為browser指定輸出字符串的編碼。?

    l?browser顯示網(wǎng)頁的時候,首先使用response中指定的編碼(jsp文件頭指定的contentType最終也反映在response上),如果未指定,則會使用網(wǎng)頁中meta項指定中的contentType。?

    3.5.?幾處設(shè)置?

    對于web應(yīng)用程序,和編碼有關(guān)的設(shè)置或者函數(shù)如下。?

    3.5.1.?jsp編譯?

    指定文件的存儲編碼,很明顯,該設(shè)置應(yīng)該置于文件的開頭。例如:<%@page?pageEncoding="GBK"%>。另外,對于一般class文件,可以在編譯的時候指定編碼。?

    3.5.2.?jsp輸出?

    指定文件輸出到browser是使用的編碼,該設(shè)置也應(yīng)該置于文件的開頭。例如:<%@?page?contentType="text/html;?charset=?GBK"?%>。該設(shè)置和response.setCharacterEncoding("GBK")等效。?

    3.5.3.?meta設(shè)置?

    指定網(wǎng)頁使用的編碼,該設(shè)置對靜態(tài)網(wǎng)頁尤其有作用。因為靜態(tài)網(wǎng)頁無法采用jsp的設(shè)置,而且也無法執(zhí)行response.setCharacterEncoding()。例如:<META?http-equiv="Content-Type"?content="text/html;?charset=GBK"?/>?

    如果同時采用了jsp輸出和meta設(shè)置兩種編碼指定方式,則jsp指定的優(yōu)先。因為jsp指定的直接體現(xiàn)在response中。?

    需要注意的是,apache有一個設(shè)置可以給無編碼指定的網(wǎng)頁指定編碼,該指定等同于jsp的編碼指定方式,所以會覆蓋靜態(tài)網(wǎng)頁中的meta指定。所以有人建議關(guān)閉該設(shè)置。?

    3.5.4.?form設(shè)置?

    當(dāng)瀏覽器提交表單的時候,可以指定相應(yīng)的編碼。例如:<form?accept-charset=?"gb2312">。一般不必不使用該設(shè)置,瀏覽器會直接使用網(wǎng)頁的編碼。?

    4.?系統(tǒng)軟件?

    下面討論幾個相關(guān)的系統(tǒng)軟件。?

    4.1.?mysql數(shù)據(jù)庫?

    很明顯,要支持多語言,應(yīng)該將數(shù)據(jù)庫的編碼設(shè)置成utf或者unicode,而utf更適合與存儲。但是,如果中文數(shù)據(jù)中包含的英文字母很少,其實unicode更為適合。?

    數(shù)據(jù)庫的編碼可以通過mysql的配置文件設(shè)置,例如default-character-set=utf8。還可以在數(shù)據(jù)庫鏈接URL中設(shè)置,例如:?useUnicode=true&characterEncoding=UTF-8。注意這兩者應(yīng)該保持一致,在新的sql版本里,在數(shù)據(jù)庫鏈接URL里可以不進(jìn)行設(shè)置,但也不能是錯誤的設(shè)置。?

    4.2.?apache?

    appache和編碼有關(guān)的配置在httpd.conf中,例如AddDefaultCharset?UTF-8。如前所述,該功能會將所有靜態(tài)頁面的編碼設(shè)置為UTF-8,最好關(guān)閉該功能。?

    另外,apache還有單獨(dú)的模塊來處理網(wǎng)頁響應(yīng)頭,其中也可能對編碼進(jìn)行設(shè)置。?

    4.3.?linux默認(rèn)編碼?

    這里所說的linux默認(rèn)編碼,是指運(yùn)行時的環(huán)境變量。兩個重要的環(huán)境變量是LC_ALL和LANG,默認(rèn)編碼會影響到j(luò)ava?URLEncode的行為,下面有描述。?

    建議都設(shè)置為"zh_CN.UTF-8"。?

    4.4.?其它?

    為了支持中文文件名,linux在加載磁盤時應(yīng)該指定字符集,例如:mount?/dev/hda5?/mnt/hda5/?-t?ntfs?-o?iocharset=gb2312。?

    另外,如前所述,使用GET方法提交的信息不支持request.setCharacterEncoding(),但可以通過tomcat的配置文件指定字符集,在tomcat的server.xml文件中,形如:<Connector?...?URIEncoding="GBK"/>。這種方法將統(tǒng)一設(shè)置所有請求,而不能針對具體頁面進(jìn)行設(shè)置,也不一定和browser使用的編碼相同,所以有時候并不是所期望的。?

    5.?URL地址?

    URL地址中含有中文字符是很麻煩的,前面描述過使用GET方法提交表單的情況,使用GET方法時,參數(shù)就是包含在URL中。?

    5.1.?URL編碼?

    對于URL中的一些特殊字符,瀏覽器會自動進(jìn)行編碼。這些字符除了"/?&"等外,還包括unicode字符,比如漢子。這時的編碼比較特殊。?

    IE有一個選項"總是使用UTF-8發(fā)送URL",當(dāng)該選項有效時,IE將會對特殊字符進(jìn)行UTF-8編碼,同時進(jìn)行URL編碼。如果改選項無效,則使用默認(rèn)編碼"GBK",并且不進(jìn)行URL編碼。但是,對于URL后面的參數(shù),則總是不進(jìn)行編碼,相當(dāng)于UTF-8選項無效。比如"中文.html?a=中文",當(dāng)UTF-8選項有效時,將發(fā)送鏈接"%e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87";而UTF-8選項無效時,將發(fā)送鏈接"\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87"。注意后者前面的"中文"兩個字只有4個字節(jié),而前者卻有18個字節(jié),這主要時URL編碼的原因。?

    當(dāng)web?server(tomcat)接收到該鏈接時,將會進(jìn)行URL解碼,即去掉"%",同時按照ISO8859-1編碼(上面已經(jīng)描述,可以使用URLEncoding來設(shè)置成其它編碼)識別。上述例子的結(jié)果分別是"\ue4\ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87"和"\u4e\u2d\u65\u87.html?a=\u4e\u2d\u65\u87",注意前者前面的"中文"兩個字恢復(fù)成了6個字符。這里用"\u",表示是unicode。?

    所以,由于客戶端設(shè)置的不同,相同的鏈接,在服務(wù)器上得到了不同結(jié)果。這個問題不少人都遇到,卻沒有很好的解決辦法。所以有的網(wǎng)站會建議用戶嘗試關(guān)閉UTF-8選項。不過,下面會描述一個更好的處理辦法。?

    5.2.?rewrite?

    熟悉的人都知道,apache有一個功能強(qiáng)大的rewrite模塊,這里不描述其功能。需要說明的是該模塊會自動將URL解碼(去除%),即完成上述web?server(tomcat)的部分功能。有相關(guān)文檔介紹說可以使用[NE]參數(shù)來關(guān)閉該功能,但我試驗并未成功,可能是因為版本(我使用的是apache?2.0.54)問題。另外,當(dāng)參數(shù)中含有"?&?"等符號的時候,該功能將導(dǎo)致系統(tǒng)得不到正常結(jié)果。?

    rewrite本身似乎完全是采用字節(jié)處理的方式,而不考慮字符串的編碼,所以不會帶來編碼問題。?

    5.3.?URLEncode.encode()?

    這是Java本身提供對的URL編碼函數(shù),完成的工作和上述UTF-8選項有效時瀏覽器所做的工作相似。值得說明的是,java已經(jīng)不贊成不指定編碼來使用該方法(deprecated)。應(yīng)該在使用的時候增加編碼指定。?

    當(dāng)不指定編碼的時候,該方法使用系統(tǒng)默認(rèn)編碼,這會導(dǎo)致軟件運(yùn)行結(jié)果得不確定。比如對于"中文",當(dāng)系統(tǒng)默認(rèn)編碼為"gb2312"時,結(jié)果是"%4e%2d%65%87",而默認(rèn)編碼為"UTF-8",結(jié)果卻是"%e4%b8%ad%e6%96%87",后續(xù)程序?qū)㈦y以處理。另外,這兒說的系統(tǒng)默認(rèn)編碼是由運(yùn)行tomcat時的環(huán)境變量LC_ALL和LANG等決定的,曾經(jīng)出現(xiàn)過tomcat重啟后就出現(xiàn)亂碼的問題,最后才郁悶的發(fā)現(xiàn)是因為修改修改了這兩個環(huán)境變量。?

    建議統(tǒng)一指定為"UTF-8"編碼,可能需要修改相應(yīng)的程序。?

    5.4.?一個解決方案?

    上面說起過,因為瀏覽器設(shè)置的不同,對于同一個鏈接,web?server收到的是不同內(nèi)容,而軟件系統(tǒng)有無法知道這中間的區(qū)別,所以這一協(xié)議目前還存在缺陷。?

    針對具體問題,不應(yīng)該僥幸認(rèn)為所有客戶的IE設(shè)置都是UTF-8有效的,也不應(yīng)該粗暴的建議用戶修改IE設(shè)置,要知道,用戶不可能去記住每一個web?server的設(shè)置。所以,接下來的解決辦法就只能是讓自己的程序多一點智能:根據(jù)內(nèi)容來分析編碼是否UTF-8。?

    比較幸運(yùn)的是UTF-8編碼相當(dāng)有規(guī)律,所以可以通過分析傳輸過來的鏈接內(nèi)容,來判斷是否是正確的UTF-8字符,如果是,則以UTF-8處理之,如果不是,則使用客戶默認(rèn)編碼(比如"GBK"),下面是一個判斷是否UTF-8的例子,如果你了解相應(yīng)規(guī)律,就容易理解。?

    public?static?boolean?isValidUtf8(byte[]?b,int?aMaxCount){?

    ???????int?lLen=b.length,lCharCount=0;?

    ???????for(int?i=0;i<lLen?&&?lCharCount<aMaxCount;++lCharCount){?

    ??????????????byte?lByte=b[i++];//to?fast?operation,?++?now,?ready?for?the?following?for(;;)?

    ??????????????if(lByte>=0)?continue;//>=0?is?normal?ascii?

    ??????????????if(lByte<(byte)0xc0?||?lByte>(byte)0xfd)?return?false;?

    ??????????????int?lCount=lByte>(byte)0xfc?5:lByte>(byte)0xf8?4?

    ?????????????????????:lByte>(byte)0xf0?3:lByte>(byte)0xe0?2:1;?

    ??????????????if(i+lCount>lLen)?return?false;?

    ??????????????for(int?j=0;j<lCount;++j,++i)?if(b[i]>=(byte)0xc0)?return?false;?

    ???????}?

    ???????return?true;?

    }?

    相應(yīng)地,一個使用上述方法的例子如下:?

    public?static?String?getUrlParam(String?aStr,String?aDefaultCharset)?

    throws?UnsupportedEncodingException{?

    ???????if(aStr==null)?return?null;?

    ???????byte[]?lBytes=aStr.getBytes("ISO-8859-1");?

    ???????return?new?String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset);?

    }?

    不過,該方法也存在缺陷,如下兩方面:?

    l?沒有包括對用戶默認(rèn)編碼的識別,這可以根據(jù)請求信息的語言來判斷,但不一定正確,因為我們有時候也會輸入一些韓文,或者其他文字。?

    l?可能會錯誤判斷UTF-8字符,一個例子是"學(xué)習(xí)"兩個字,其GBK編碼是"?\xd1\xa7\xcf\xb0",如果使用上述isValidUtf8方法判斷,將返回true。可以考慮使用更嚴(yán)格的判斷方法,不過估計效果不大。?

    有一個例子可以證明google也遇到了上述問題,而且也采用了和上述相似的處理方法,比如,如果在地址欄中輸入"http://www.google.com/search?hl=zh-CN&newwindow=1&q=學(xué)習(xí)",google將無法正確識別,而其他漢字一般能夠正常識別。?

    最后,應(yīng)該補(bǔ)充說明一下,如果不使用rewrite規(guī)則,或者通過表單提交數(shù)據(jù),其實并不一定會遇到上述問題,因為這時可以在提交數(shù)據(jù)時指定希望的編碼。另外,中文文件名確實會帶來問題,應(yīng)該謹(jǐn)慎使用。?

    6.?其它?

    下面描述一些和編碼有關(guān)的其他問題。?

    6.1.?SecureCRT?

    除了瀏覽器和控制臺與編碼有關(guān)外,一些客戶端也很有關(guān)系。比如在使用SecureCRT連接linux時,應(yīng)該讓SecureCRT的顯示編碼(不同的session,可以有不同的編碼設(shè)置)和linux的編碼環(huán)境變量保持一致。否則看到的一些幫助信息,就可能是亂碼。?

    另外,mysql有自己的編碼設(shè)置,也應(yīng)該保持和SecureCRT的顯示編碼一致。否則通過SecureCRT執(zhí)行sql語句的時候,可能無法處理中文字符,查詢結(jié)果也會出現(xiàn)亂碼。?

    對于Utf-8文件,很多編輯器(比如記事本)會在文件開頭增加三個不可見的標(biāo)志字節(jié),如果作為mysql的輸入文件,則必須要去掉這三個字符。(用linux的vi保存可以去掉這三個字符)。一個有趣的現(xiàn)象是,在中文windows下,創(chuàng)建一個新txt文件,用記事本打開,輸入"連通"兩個字,保存,再打開,你會發(fā)現(xiàn)兩個字沒了,只留下一個小黑點。?

    6.2.?過濾器?

    如果需要統(tǒng)一設(shè)置編碼,則通過filter進(jìn)行設(shè)置是個不錯的選擇。在filter?class中,可以統(tǒng)一為需要的請求或者回應(yīng)設(shè)置編碼。參加上述setCharacterEncoding()。這個類apache已經(jīng)給出了可以直接使用的例子SetCharacterEncodingFilter。?

    6.3.?POST和GET?

    很明顯,以POST提交信息時,URL有更好的可讀性,而且可以方便的使用setCharacterEncoding()來處理字符集問題。但GET方法形成的URL能夠更容易表達(dá)網(wǎng)頁的實際內(nèi)容,也能夠用于收藏。?

    從統(tǒng)一的角度考慮問題,建議采用GET方法,這要求在程序中獲得參數(shù)是進(jìn)行特殊處理,而無法使用setCharacterEncoding()的便利,如果不考慮rewrite,就不存在IE的UTF-8問題,可以考慮通過設(shè)置URIEncoding來方便獲取URL中的參數(shù)。?

    6.4.?簡繁體編碼轉(zhuǎn)換?

    GBK同時包含簡體和繁體編碼,也就是說同一個字,由于編碼不同,在GBK編碼下屬于兩個字。有時候,為了正確取得完整的結(jié)果,應(yīng)該將繁體和簡體進(jìn)行統(tǒng)一。可以考慮將UTF、GBK中的所有繁體字,轉(zhuǎn)換為相應(yīng)的簡體字,BIG5編碼的數(shù)據(jù),也應(yīng)該轉(zhuǎn)化成相應(yīng)的簡體字。當(dāng)然,仍舊以UTF編碼存儲。?

    例如,對于"語言??言",用UTF表示為"\xE8\xAF\xAD\xE8\xA8\x80?\xE8\xAA\x9E\xE8\xA8\x80",進(jìn)行簡繁體編碼轉(zhuǎn)換后應(yīng)該是兩個相同的?"\xE8\xAF\xAD\xE8\xA8\x80>"。?
    ?

    posted @ 2006-08-30 17:51 xnabx 閱讀(176) | 評論 (0)編輯 收藏
    URL
    http://sz.eeju.com/show_rent_99461.htm

    http://sz.eeju.com/show_rent_98823.htm

    http://sz.eeju.com/show_rent_96082.htm

    http://sz.eeju.com/show_rent_99193.htm

    http://sz.eeju.com/show_rent_99461.htm

    http://sz.eeju.com/show_rent_99181.htm

    http://rent.sz.soufun.com/cz/CZ_MLS_17845812.htm

    http://rent.sz.soufun.com/cz/CZ_MLS_17940110.htm

    http://rent.sz.soufun.com/cz/CZ_MLS_17852140.htm?***
    posted @ 2006-03-28 15:22 xnabx 閱讀(164) | 評論 (0)編輯 收藏

    插入排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;
    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class InsertSort implements SortUtil.Sort{

    ??? /* (non-Javadoc)
    ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    ???? */
    ??? public void sort(int[] data) {
    ??????? int temp;
    ??????? for(int i=1;i<data.length;i++){
    ??????????? for(int j=i;(j>0)&&(data[j]<data[j-1]);j--){
    ??????????????? SortUtil.swap(data,j,j-1);
    ??????????? }
    ??????? }???????
    ??? }

    }
    冒泡排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class BubbleSort implements SortUtil.Sort{

    ??? /* (non-Javadoc)
    ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    ???? */
    ??? public void sort(int[] data) {
    ??????? int temp;
    ??????? for(int i=0;i<data.length;i++){
    ??????????? for(int j=data.length-1;j>i;j--){
    ??????????????? if(data[j]<data[j-1]){
    ??????????????????? SortUtil.swap(data,j,j-1);
    ??????????????? }
    ??????????? }
    ??????? }
    ??? }

    }

    選擇排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class SelectionSort implements SortUtil.Sort {

    ??? /*
    ???? * (non-Javadoc)
    ???? *
    ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    ???? */
    ??? public void sort(int[] data) {
    ??????? int temp;
    ??????? for (int i = 0; i < data.length; i++) {
    ??????????? int lowIndex = i;
    ??????????? for (int j = data.length - 1; j > i; j--) {
    ??????????????? if (data[j] < data[lowIndex]) {
    ??????????????????? lowIndex = j;
    ??????????????? }
    ??????????? }
    ??????????? SortUtil.swap(data,i,lowIndex);
    ??????? }
    ??? }

    }

    Shell排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class ShellSort implements SortUtil.Sort{

    ??? /* (non-Javadoc)
    ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    ???? */
    ??? public void sort(int[] data) {
    ??????? for(int i=data.length/2;i>2;i/=2){
    ??????????? for(int j=0;j<i;j++){
    ??????????????? insertSort(data,j,i);
    ??????????? }
    ??????? }
    ??????? insertSort(data,0,1);
    ??? }

    ??? /**
    ???? * @param data
    ???? * @param j
    ???? * @param i
    ???? */
    ??? private void insertSort(int[] data, int start, int inc) {
    ??????? int temp;
    ??????? for(int i=start+inc;i<data.length;i+=inc){
    ??????????? for(int j=i;(j>=inc)&&(data[j]<data[j-inc]);j-=inc){
    ??????????????? SortUtil.swap(data,j,j-inc);
    ??????????? }
    ??????? }
    ??? }

    }

    快速排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class QuickSort implements SortUtil.Sort{

    ??? /* (non-Javadoc)
    ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    ???? */
    ??? public void sort(int[] data) {
    ??????? quickSort(data,0,data.length-1);???????
    ??? }
    ??? private void quickSort(int[] data,int i,int j){
    ??????? int pivotIndex=(i+j)/2;
    ??????? //swap
    ??????? SortUtil.swap(data,pivotIndex,j);
    ???????
    ??????? int k=partition(data,i-1,j,data[j]);
    ??????? SortUtil.swap(data,k,j);
    ??????? if((k-i)>1) quickSort(data,i,k-1);
    ??????? if((j-k)>1) quickSort(data,k+1,j);
    ???????
    ??? }
    ??? /**
    ???? * @param data
    ???? * @param i
    ???? * @param j
    ???? * @return
    ???? */
    ??? private int partition(int[] data, int l, int r,int pivot) {
    ??????? do{
    ?????????? while(data[++l]<pivot);
    ?????????? while((r!=0)&&data[--r]>pivot);
    ?????????? SortUtil.swap(data,l,r);
    ??????? }
    ??????? while(l<r);
    ??????? SortUtil.swap(data,l,r);???????
    ??????? return l;
    ??? }

    }
    改進(jìn)后的快速排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class ImprovedQuickSort implements SortUtil.Sort {

    ??? private static int MAX_STACK_SIZE=4096;
    ??? private static int THRESHOLD=10;
    ??? /* (non-Javadoc)
    ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    ???? */
    ??? public void sort(int[] data) {
    ??????? int[] stack=new int[MAX_STACK_SIZE];
    ???????
    ??????? int top=-1;
    ??????? int pivot;
    ??????? int pivotIndex,l,r;
    ???????
    ??????? stack[++top]=0;
    ??????? stack[++top]=data.length-1;
    ???????
    ??????? while(top>0){
    ??????????? int j=stack[top--];
    ??????????? int i=stack[top--];
    ???????????
    ??????????? pivotIndex=(i+j)/2;
    ??????????? pivot=data[pivotIndex];
    ???????????
    ??????????? SortUtil.swap(data,pivotIndex,j);
    ???????????
    ??????????? //partition
    ??????????? l=i-1;
    ??????????? r=j;
    ??????????? do{
    ??????????????? while(data[++l]<pivot);
    ??????????????? while((r!=0)&&(data[--r]>pivot));
    ??????????????? SortUtil.swap(data,l,r);
    ??????????? }
    ??????????? while(l<r);
    ??????????? SortUtil.swap(data,l,r);
    ??????????? SortUtil.swap(data,l,j);
    ???????????
    ??????????? if((l-i)>THRESHOLD){
    ??????????????? stack[++top]=i;
    ??????????????? stack[++top]=l-1;
    ??????????? }
    ??????????? if((j-l)>THRESHOLD){
    ??????????????? stack[++top]=l+1;
    ??????????????? stack[++top]=j;
    ??????????? }
    ???????????
    ??????? }
    ??????? //new InsertSort().sort(data);
    ??????? insertSort(data);
    ??? }
    ??? /**
    ???? * @param data
    ???? */
    ??? private void insertSort(int[] data) {
    ??????? int temp;
    ??????? for(int i=1;i<data.length;i++){
    ??????????? for(int j=i;(j>0)&&(data[j]<data[j-1]);j--){
    ??????????????? SortUtil.swap(data,j,j-1);
    ??????????? }
    ??????? }??????
    ??? }

    }

    歸并排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class MergeSort implements SortUtil.Sort{

    ??? /* (non-Javadoc)
    ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    ???? */
    ??? public void sort(int[] data) {
    ??????? int[] temp=new int[data.length];
    ??????? mergeSort(data,temp,0,data.length-1);
    ??? }
    ???
    ??? private void mergeSort(int[] data,int[] temp,int l,int r){
    ??????? int mid=(l+r)/2;
    ??????? if(l==r) return ;
    ??????? mergeSort(data,temp,l,mid);
    ??????? mergeSort(data,temp,mid+1,r);
    ??????? for(int i=l;i<=r;i++){
    ??????????? temp[i]=data[i];
    ??????? }
    ??????? int i1=l;
    ??????? int i2=mid+1;
    ??????? for(int cur=l;cur<=r;cur++){
    ??????????? if(i1==mid+1)
    ??????????????? data[cur]=temp[i2++];
    ??????????? else if(i2>r)
    ??????????????? data[cur]=temp[i1++];
    ??????????? else if(temp[i1]<temp[i2])
    ??????????????? data[cur]=temp[i1++];
    ??????????? else
    ??????????????? data[cur]=temp[i2++];???????????
    ??????? }
    ??? }

    }

    改進(jìn)后的歸并排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class ImprovedMergeSort implements SortUtil.Sort {

    ??? private static final int THRESHOLD = 10;

    ??? /*
    ???? * (non-Javadoc)
    ???? *
    ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    ???? */
    ??? public void sort(int[] data) {
    ??????? int[] temp=new int[data.length];
    ??????? mergeSort(data,temp,0,data.length-1);
    ??? }

    ??? private void mergeSort(int[] data, int[] temp, int l, int r) {
    ??????? int i, j, k;
    ??????? int mid = (l + r) / 2;
    ??????? if (l == r)
    ??????????? return;
    ??????? if ((mid - l) >= THRESHOLD)
    ??????????? mergeSort(data, temp, l, mid);
    ??????? else
    ??????????? insertSort(data, l, mid - l + 1);
    ??????? if ((r - mid) > THRESHOLD)
    ??????????? mergeSort(data, temp, mid + 1, r);
    ??????? else
    ??????????? insertSort(data, mid + 1, r - mid);

    ??????? for (i = l; i <= mid; i++) {
    ??????????? temp[i] = data[i];
    ??????? }
    ??????? for (j = 1; j <= r - mid; j++) {
    ??????????? temp[r - j + 1] = data[j + mid];
    ??????? }
    ??????? int a = temp[l];
    ??????? int b = temp[r];
    ??????? for (i = l, j = r, k = l; k <= r; k++) {
    ??????????? if (a < b) {
    ??????????????? data[k] = temp[i++];
    ??????????????? a = temp[i];
    ??????????? } else {
    ??????????????? data[k] = temp[j--];
    ??????????????? b = temp[j];
    ??????????? }
    ??????? }
    ??? }

    ??? /**
    ???? * @param data
    ???? * @param l
    ???? * @param i
    ???? */
    ??? private void insertSort(int[] data, int start, int len) {
    ??????? for(int i=start+1;i<start+len;i++){
    ??????????? for(int j=i;(j>start) && data[j]<data[j-1];j--){
    ??????????????? SortUtil.swap(data,j,j-1);
    ??????????? }
    ??????? }
    ??? }

    }
    堆排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class HeapSort implements SortUtil.Sort{

    ??? /* (non-Javadoc)
    ???? * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])
    ???? */
    ??? public void sort(int[] data) {
    ??????? MaxHeap h=new MaxHeap();
    ??????? h.init(data);
    ??????? for(int i=0;i<data.length;i++)
    ??????????? h.remove();
    ??????? System.arraycopy(h.queue,1,data,0,data.length);
    ??? }


    ???? private static class MaxHeap{
    ????????
    ???????
    ??????? void init(int[] data){
    ??????????? this.queue=new int[data.length+1];
    ??????????? for(int i=0;i<data.length;i++){
    ??????????????? queue[++size]=data[i];
    ??????????????? fixUp(size);
    ??????????? }
    ??????? }
    ????????
    ??????? private int size=0;

    ??????? private int[] queue;
    ???????????????
    ??????? public int get() {
    ??????????? return queue[1];
    ??????? }

    ??????? public void remove() {
    ??????????? SortUtil.swap(queue,1,size--);
    ??????????? fixDown(1);
    ??????? }
    ??????? //fixdown
    ??????? private void fixDown(int k) {
    ??????????? int j;
    ??????????? while ((j = k << 1) <= size) {
    ??????????????? if (j < size && queue[j]<queue[j+1])
    ??????????????????? j++;
    ??????????????? if (queue[k]>queue[j]) //不用交換
    ??????????????????? break;
    ??????????????? SortUtil.swap(queue,j,k);
    ??????????????? k = j;
    ??????????? }
    ??????? }
    ??????? private void fixUp(int k) {
    ??????????? while (k > 1) {
    ??????????????? int j = k >> 1;
    ??????????????? if (queue[j]>queue[k])
    ??????????????????? break;
    ??????????????? SortUtil.swap(queue,j,k);
    ??????????????? k = j;
    ??????????? }
    ??????? }

    ??? }

    }

    ?

    SortUtil:

    package org.rut.util.algorithm;

    import org.rut.util.algorithm.support.BubbleSort;
    import org.rut.util.algorithm.support.HeapSort;
    import org.rut.util.algorithm.support.ImprovedMergeSort;
    import org.rut.util.algorithm.support.ImprovedQuickSort;
    import org.rut.util.algorithm.support.InsertSort;
    import org.rut.util.algorithm.support.MergeSort;
    import org.rut.util.algorithm.support.QuickSort;
    import org.rut.util.algorithm.support.SelectionSort;
    import org.rut.util.algorithm.support.ShellSort;

    /**
    ?* @author treeroot
    ?* @since 2006-2-2
    ?* @version 1.0
    ?*/
    public class SortUtil {
    ??? public final static int INSERT = 1;

    ??? public final static int BUBBLE = 2;

    ??? public final static int SELECTION = 3;

    ??? public final static int SHELL = 4;

    ??? public final static int QUICK = 5;

    ??? public final static int IMPROVED_QUICK = 6;

    ??? public final static int MERGE = 7;

    ??? public final static int IMPROVED_MERGE = 8;

    ??? public final static int HEAP = 9;

    ??? public static void sort(int[] data) {
    ??????? sort(data, IMPROVED_QUICK);
    ??? }
    ??? private static String[] name={
    ??????????? "insert","bubble","selection","shell","quick","improved_quick","merge","improved_merge","heap"
    ??? };
    ???
    ??? private static Sort[] impl=new Sort[]{
    ??????????? new InsertSort(),
    ??????????? new BubbleSort(),
    ??????????? new SelectionSort(),
    ??????????? new ShellSort(),
    ??????????? new QuickSort(),
    ??????????? new ImprovedQuickSort(),
    ??????????? new MergeSort(),
    ??????????? new ImprovedMergeSort(),
    ??????????? new HeapSort()
    ??? };

    ??? public static String toString(int algorithm){
    ??????? return name[algorithm-1];
    ??? }
    ???
    ??? public static void sort(int[] data, int algorithm) {
    ??????? impl[algorithm-1].sort(data);
    ??? }

    ??? public static interface Sort {
    ??????? public void sort(int[] data);
    ??? }

    ??? public static void swap(int[] data, int i, int j) {
    ??????? int temp = data[i];
    ??????? data[i] = data[j];
    ??????? data[j] = temp;
    ??? }
    }

    posted @ 2006-03-27 17:58 xnabx 閱讀(150) | 評論 (0)編輯 收藏
    Unicode解決方案
    Unicode:寬字節(jié)字符集(摘自windows核心編程)

    UnicodeAppleXerox公司于1988年建立的一個技術(shù)標(biāo)準(zhǔn)。1991年,成立了一個集團(tuán)機(jī)構(gòu)負(fù)責(zé)Unicode的開發(fā)和推廣應(yīng)用。該集團(tuán)由AppleCompaqIBMMicrosoftOracleSilicon ? Graphics, ? Inc.SybaseUnisysXerox等公司組成。該集團(tuán)負(fù)責(zé)維護(hù)Unicode標(biāo)準(zhǔn)。
    Unicode
    提供了一種簡單而又一致的表示字符串的方法。Unicode字符串中的所有字符都是16位的(兩個字節(jié))。它沒有專門的字節(jié)來指明下一個字節(jié)是屬于同一個字符的組成部分,還是一個新字符。這意味著你只需要對指針進(jìn)行遞增或遞減,就可以遍歷字符串中的各個字符,不再需要調(diào)用CharNext之類的函數(shù)。由于Unicode用一個16位的值來表示每個字符,因此總共可以得到65000個字符,這樣,它就能夠?qū)κ澜绺鲊臅嫖淖种械乃凶址M(jìn)行編碼,遠(yuǎn)遠(yuǎn)超過了單字節(jié)字符集的256個字符的數(shù)目。




    我們面臨的基本問題是世界上的書寫語言不能簡單地用256個8位代碼表示。以前的解決方案包括代碼頁和DBCS已被證明是不能滿足需要的,而且也是笨拙的。那什么才是真正的解決方案呢?

    身為程序編寫者,我們經(jīng)歷過這類問題。如果事情太多,用8位數(shù)值已經(jīng)不能表示,那么我們就試更寬的值,例如16位值。而且這很有趣的,正是Unicode被制定的原因。與混亂的256個字符代碼映像,以及含有一些1字節(jié)代碼和一些2字節(jié)代碼的雙字節(jié)字符集不同,Unicode是統(tǒng)一的16位系統(tǒng),這樣就允許表示65,536個字符。這對表示所有字符及世界上使用象形文字的語言,包括一系列的數(shù)學(xué)、符號和貨幣單位符號的集合來說是充裕的。

    明白Unicode和DBCS之間的區(qū)別很重要。Unicode使用(特別在C程序設(shè)計語言環(huán)境里)“寬字符集”。“Unicode中的每個字符都是16位寬而不是8位寬。”在Unicode中,沒有單單使用8位數(shù)值的意義存在。相比之下,在雙字節(jié)字符集中我們?nèi)匀惶幚?位數(shù)值。有些字節(jié)自身定義字符,而某些字節(jié)則顯示需要和另一個字節(jié)共同定義一個字符。

    處理DBCS字符串非常雜亂,但是處理Unicode文字則像處理有秩序的文字。您也許會高興地知道前128個Unicode字符(16位代碼從0x0000到0x007F)就是ASCII字符,而接下來的128個Unicode字符(代碼從0x0080到0x00FF)是ISO ? 8859-1對ASCII的擴(kuò)展。Unicode中不同部分的字符都同樣基于現(xiàn)有的標(biāo)準(zhǔn)。這是為了便于轉(zhuǎn)換。希臘字母表使用從0x0370到0x03FF的代碼,斯拉夫語使用從0x0400到0x04FF的代碼,美國使用從0x0530到0x058F的代碼,希伯來語使用從0x0590到0x05FF的代碼。中國、日本和韓國的象形文字(總稱為CJK)占用了從0x3000到0x9FFF的代碼。

    Unicode的最大好處是這里只有一個字符集,沒有一點含糊。Unicode實際上是個人計算機(jī)行業(yè)中幾乎每個重要公司共同合作的結(jié)果,并且它與ISO ? 10646-1標(biāo)準(zhǔn)中的代碼是一一對應(yīng)的。Unicode的重要參考文獻(xiàn)是《The ? Unicode ? Standard,Version ? 2.0》(Addison-Wesley出版社,1996年)。這是一本特別的書,它以其它文件少有的方式顯示了世界上書寫語言的豐富性和多樣性。此外,該書還提供了開發(fā)Unicode的基本原理和細(xì)節(jié)。

    Unicode有缺點嗎?當(dāng)然有。Unicode字符串占用的內(nèi)存是ASCII字符串的兩倍。(然而壓縮文件有助于極大地減少文件所占的磁盤空間。)但也許最糟的缺點是:人們相對來說還不習(xí)慣使用Unicode。身為程序編寫者,這就是我們的工作

    posted @ 2006-03-27 17:49 xnabx 閱讀(148) | 評論 (0)編輯 收藏

    插件下載地址:
    http://www.delphibbs.com/keylife/images/u88173/csdnkantie.rar
    下載后解壓到myIE的plugin目錄即可。

    例如我的解壓后的目錄:
    D:\programs\Maxthon\Plugin\csdnkantie\

    效果圖:

    http://blog.csdn.net/images/blog_csdn_net/pigo/36738/o_casdnkanite001.gif

    http://blog.csdn.net/images/blog_csdn_net/pigo/36738/o_casdnkanite001.gif

    posted @ 2006-03-27 17:20 xnabx 閱讀(122) | 評論 (0)編輯 收藏
    pop-ent.21cn.com
    @shareinfo.com.cn
    posted @ 2006-03-27 16:51 xnabx 閱讀(143) | 評論 (0)編輯 收藏

    在Connection上調(diào)用close方法會關(guān)閉Statement和ResultSet嗎?

    級聯(lián)的關(guān)閉這聽起來好像很有道理,而且在很多地方這樣做也是正確的,通常這樣寫
    Connection con = getConnection();//getConnection is your method
    PreparedStatement ps = con.prepareStatement(sql);
    ResultSet rs = ps.executeQuery();
    ……
    ///rs.close();
    ///ps.close();
    con.close();? // NO!
    這樣做的問題在于Connection是個接口,它的close實現(xiàn)可能是多種多樣的。在普通情況下,你用 DriverManager.getConnection()得到一個Connection實例,調(diào)用它的close方法會關(guān)閉Statement和 ResultSet。但是在很多時候,你需要使用數(shù)據(jù)庫連接池,在連接池中的得到的Connection上調(diào)用close方法的時候,Connection可能并沒有被釋放,而是回到了連接池中。它以后可能被其它代碼取出來用。如果沒有釋放Statement和ResultSet,那么在Connection上沒有關(guān)閉的Statement和ResultSet可能會越來越多,那么……
    相反,我看到過這樣的說法,有人把Connection關(guān)閉了,卻繼續(xù)使用ResultSet,認(rèn)為這樣是可以的,引發(fā)了激烈的討論,到底是怎么回事就不用我多說了吧。

    所以我們必須很小心的釋放數(shù)據(jù)庫資源,下面的代碼片斷展示了這個過程

    Connection con = null;
    PreparedStatement ps = null;
    ResultSet rs = null;

    try {
    ??? con = getConnection();//getConnection is your method
    ??? ps = con.prepareStatement(sql);
    ??? rs = ps.executeQuery();
    ??? ///...........
    }
    catch (SQLException ex) {
    ??? ///錯誤處理
    }
    finally{
    ??? try {
    ??????? if(ps!=null)
    ??????????? ps.close();
    ??? }
    ??? catch (SQLException ex) {
    ??????? ///錯誤處理
    ??? }
    ??? try{
    ??????? if(con!=null)
    ??????????? con.close();
    ??? }
    ??? catch (SQLException ex) {
    ??????? ///錯誤處理
    ??? }
    }

    ?

    posted @ 2006-03-23 22:27 xnabx 閱讀(505) | 評論 (0)編輯 收藏

    1. Open:? Internet Options --> Content --> AutoComplete

    2. Click button: ?'Clear Forms' and 'Clear Passwords'

    posted @ 2006-03-23 22:07 xnabx 閱讀(344) | 評論 (0)編輯 收藏

    public class TranCharset {

    ??? private static final String PRE_FIX_UTF = "&#x";
    ??? private static final String POS_FIX_UTF = ";";

    ??? public TranCharset() {
    ??? }

    ??? /**
    ???? * Translate charset encoding to unicode
    ???? *
    ???? * @param sTemp charset encoding is gb2312
    ???? * @return charset encoding is unicode
    ???? */
    ??? public static String XmlFormalize(String sTemp) {
    ??????? StringBuffer sb = new StringBuffer();

    ??????? if (sTemp == null || sTemp.equals("")) {
    ??????????? return "";
    ??????? }
    ??????? String s = TranCharset.TranEncodeTOGB(sTemp);
    ??????? for (int i = 0; i < s.length(); i++) {
    ??????????? char cChar = s.charAt(i);
    ??????????? if (TranCharset.isGB2312(cChar)) {
    ??????????????? sb.append(PRE_FIX_UTF);
    ??????????????? sb.append(Integer.toHexString(cChar));
    ??????????????? sb.append(POS_FIX_UTF);
    ??????????? } else {
    ??????????????? switch ((int) cChar) {
    ??????????????????? case 32:
    ??????????????????????? sb.append("&#32;");
    ??????????????????????? break;
    ??????????????????? case 34:
    ??????????????????????? sb.append("&quot;");
    ??????????????????????? break;
    ??????????????????? case 38:
    ??????????????????????? sb.append("&amp;");
    ??????????????????????? break;
    ??????????????????? case 60:
    ??????????????????????? sb.append("&lt;");
    ??????????????????????? break;
    ??????????????????? case 62:
    ??????????????????????? sb.append("&gt;");
    ??????????????????????? break;
    ??????????????????? default:
    ??????????????????????? sb.append(cChar);
    ??????????????? }
    ??????????? }
    ??????? }
    ??????? return sb.toString();
    ??? }

    ??? /**
    ???? * 將字符串編碼格式轉(zhuǎn)成GB2312
    ???? *
    ???? * @param str
    ???? * @return
    ???? */
    ??? public static String TranEncodeTOGB(String str) {
    ??????? try {
    ??????????? String strEncode = TranCharset.getEncoding(str);
    ??????????? String temp = new String(str.getBytes(strEncode), "GB2312");
    ??????????? return temp;
    ??????? } catch (java.io.IOException ex) {

    ??????????? return null;
    ??????? }
    ??? }

    ??? /**
    ???? * 判斷輸入字符是否為gb2312的編碼格式
    ???? *
    ???? * @param c 輸入字符
    ???? * @return 如果是gb2312返回真,否則返回假
    ???? */
    ??? public static boolean isGB2312(char c) {
    ??????? Character ch = new Character(c);
    ??????? String sCh = ch.toString();
    ??????? try {
    ??????????? byte[] bb = sCh.getBytes("gb2312");
    ??????????? if (bb.length > 1) {
    ??????????????? return true;
    ??????????? }
    ??????? } catch (java.io.UnsupportedEncodingException ex) {
    ??????????? return false;
    ??????? }
    ??????? return false;
    ??? }

    ??? /**
    ???? * 判斷字符串的編碼
    ???? *
    ???? * @param str
    ???? * @return
    ???? */
    ??? public static String getEncoding(String str) {
    ??????? String encode = "GB2312";
    ??????? try {
    ??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
    ??????????????? String s = encode;
    ??????????????? return s;
    ??????????? }
    ??????? } catch (Exception exception) {
    ??????? }
    ??????? encode = "ISO-8859-1";
    ??????? try {
    ??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
    ??????????????? String s1 = encode;
    ??????????????? return s1;
    ??????????? }
    ??????? } catch (Exception exception1) {
    ??????? }
    ??????? encode = "UTF-8";
    ??????? try {
    ??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
    ??????????????? String s2 = encode;
    ??????????????? return s2;
    ??????????? }
    ??????? } catch (Exception exception2) {
    ??????? }
    ??????? encode = "GBK";
    ??????? try {
    ??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
    ??????????????? String s3 = encode;
    ??????????????? return s3;
    ??????????? }
    ??????? } catch (Exception exception3) {
    ??????? }
    ??????? encode = "BIG5";
    ??????? try {
    ??????????? if (str.equals(new String(str.getBytes(encode), encode))) {
    ??????????????? String s4 = encode;
    ??????????????? return s4;
    ??????????? }
    ??????? } catch (Exception exception3) {
    ??????? }
    ??????? return "";
    ??? }

    ??? public static void main(String args[]) {
    ??????? System.out.println(XmlFormalize("下載"));
    ??? }
    }

    posted @ 2006-03-23 09:16 xnabx 閱讀(150) | 評論 (0)編輯 收藏

    問題:
    如何在文本框中只允許輸入漢字,字母數(shù)字或者其他符號文字都不可以呢?

    處理:
    //javascript

    var?? re=/[^\x00-\xff]/g;
    if(re.test(你要測試的值))
    {
    ????? //是漢字
    }

    注:用ascII碼控制。好像漢字都是負(fù)數(shù)


    System.out.println(Pattern.compile("[\u4e00-\u9fa5]").matcher("a").find());

    //[\u4e00-\u9fa5] 中文的正則表達(dá)式
    //"a" 你想判斷的字符

    posted @ 2006-03-22 22:39 xnabx 閱讀(509) | 評論 (1)編輯 收藏

    問題:

    在ArrayList 應(yīng)用中有這樣的代碼:

    ArrayList a=new ArrayList();

    a.add(...);

    Iterator i=a.iterator();

    理解:Iterator i=a.iterator();

    Iterator 是一個接口,在上面a.iterator()方法的作用是返回一個接口
    hasmore(),next()是怎么被實現(xiàn)的?

    處理:
    迭代模式
    ArrayList內(nèi)部有一個實現(xiàn)了Iterator 接口的類,a.iterator就是返回它內(nèi)部類的一個實例,即返回一個實現(xiàn)了的iterator接口的類。

    接口是一個類型,相當(dāng)于一個父類型(supertype),可以用一個接口引用一個實現(xiàn)了此接口的類的實例。這樣只能用接口提供的方法來訪問此對象,可以限制訪問,隱藏具體實現(xiàn)。


    posted @ 2006-03-22 22:35 xnabx 閱讀(245) | 評論 (0)編輯 收藏
    我想遍歷所有key為username的值,比如:
    每一個登陸用戶都有一個username的session,我如何判斷有多少個這樣的session及其值呢?

    處理:
    HttpSessionBindingListener進(jìn)行監(jiān)聽,維護(hù)一個全局變量
    posted @ 2006-03-22 17:13 xnabx 閱讀(1095) | 評論 (0)編輯 收藏

    首先明確一下,樓主的問題應(yīng)該是比較 JDK 和 JRE (而不是 JVM,因為 JDK 和 JRE 里面都包含 JVM)。

    顧名思義,JDK 比 JRE 多出來的東西,就是在開發(fā)過程中要用到的一些東西,比如 javac、javadoc、keytool 等工具,還有其它的一些東西(比如 API 文檔)。一般來說,這些東西在軟件開發(fā)完成交付運(yùn)行之后就用不到了。不過也有例外,比如要在 Tomcat 里跑 JSP 的話,就需要 javac。

    posted @ 2006-03-22 16:14 xnabx 閱讀(133) | 評論 (0)編輯 收藏

    public:公有的,說明該類成員可被所有的對象使用

    protected:保護(hù)的,說明該類成員能被同一類中的其他成員,或其子類成員,或同一包中的其他類訪問,不能被其他包的非子類訪問

    無:默認(rèn)的.當(dāng)修飾符默認(rèn)時,說明該類成員能被同一類中的其他成員,或同一包中的其他類訪問,不能被其他包的類訪問

    private:私有的,說明該類成員只能被同一類中的其他成員訪問,不能被其他類的成員訪問,也不能被子類成員訪問.

    posted @ 2006-03-22 15:57 xnabx 閱讀(167) | 評論 (0)編輯 收藏
    1. 有一個ArrayList,里面包含N個Integer,其中的Integer都是由1至N+1的數(shù)字構(gòu)成,并且不重復(fù),但是有一個1至N+1的數(shù)字對應(yīng)的Integer

    不存在ArrayList中,求該數(shù)。

    public static void main(String[] args){

    ArrayList list= new ArrayList();
    list.add(Integet(7));
    list.add(Integet(8));
    list.add(Integet(1));
    list.add(Integet(2));
    list.add(Integet(3));
    list.add(Integet(4));
    list.add(Integet(5));

    }


    public int getMissing(ArrayList list){
    int len = list.size();
    for (int i = 1; i <= len; i++) {
    int j = 0;
    while (j < len) {
    Integer Val = (Integer) list.get(j);
    int value = Val.intValue();
    if (i == value)
    break;
    j++;
    }
    if (j == len) {
    return j;
    }
    }
    return -1;
    }

    2. 有一個二叉樹類如下。然后寫出遍歷二叉樹的方法printTree。
    class BinaryTree{
    class Node{
    ? String value;
    ? Node leftNode;
    ? Node rightNode;
    }
    public void printTree(Node root){
    ? reDo(root,0);
    }

    public void reDo(Node node,int depth){
    ? if(node != null) {
    ??? System.out.println(space()+node.value);
    ??? reDo(node.leftNode,depth+1);
    ??? reDo(node.rightNode,depth+1);
    ? }
    ?????
    }

    public String space(int len){
    ?? StringBuffer bs = new StringBuffer();
    ?? for(int i=0; i<bs.length();i++){
    ??? bs.append(" ");
    ?? }
    }
    }

    3. 有int型數(shù)字如下,123,1234,12345,123456,1234567,12345678,123456789
    求一個方法,輸出123 1,234 12,345 123,456 1,234,567 12,345,678 123,456,789

    public String printComma(int input){
    StringBuffer bs = new StringBuffer(input + "");
    int index = bs.length() - 3;
    while (index > 0) {
    ? bs.insert(index, ",");
    ? index = index - 3;
    }
    return bs.toString();
    }

    4.equals(),hasCode()的作用。

    5.Object對象有哪些方法?
    ? equals(),clone(),notify(),notifyAll(),wait(),wait(long time),wait(long time,int nanos)
    ? hasCode(),toString(),getClass()。

    6.RuntimeException,非RuntimeException的區(qū)別和例子。

    7.Singleton模式

    8.共享數(shù)據(jù)在web中的范圍
    ? page,request,seesion,application

    9.Servlet的生命周期。
    ? servlet有良好的生存期定義,包括加載,實例化,初始化,處理請求,服務(wù)結(jié)束。由javax.servlet.Servlet接口以下方法表達(dá)
    ? init(),service(),destroy()。

    10.abstract和interface的區(qū)別。
    ? abstract中可以有自己方法的定義和說明,interface只是存在變量和方法的定義。當(dāng)需要的時候,我們可以inplements多個接口,但是只能

    extends一個類。

    11.實現(xiàn)多線程有哪幾種方法。
    第一種,class MyThread extends Thread{..}? MyThread t = new MyThread(); t.start();
    第二中,class UrThread implements Runnable{...} Thread t = new Thread(new UrThread()); t.start();

    12.ArrayList和Vector的區(qū)別。
    ? Vector中的方法是synchronized的,性能上較ArrayList差點。
    ? 當(dāng)增長時,Vector默認(rèn)增長原來的一倍,ArrayList默認(rèn)增長原來的一半。

    13.java實現(xiàn)序列化的方法是實現(xiàn)serializable接口,具體怎么做。
    ??
    14.String a = "test"; String b = new String("test"); a==b (false)
    ?? String c = "te"+"st"; a==c (true)

    15.
    public synchronized void aMethod1(){

    }

    public void b aMethod(){
    synchronized("test"){
    ?
    }
    }

    A a1 = new A();
    A a2 = new A();

    a1.aMethod1();
    a2.aMethod1();//不需要等待

    a1.aMethod2();
    a2.aMethod2();//需要等待

    16.編程性能方法的討論,ArrayList,HashMap,StringBuffer。

    17.Struts的DispatchAction,Action的區(qū)別。RequestProcessor的作用。


    roypayne(java = 星際) ( 一級(初級)) 信譽(yù):100 2006-03-22 09:51:00 得分:0
    ?
    Top
    treeroot(旗魯特) ( 兩星(中級)) 信譽(yù):106 2006-03-22 10:23:00 得分:0
    ?
    Top
    huyc_fly() ( 二級(初級)) 信譽(yù):100 2006-03-22 11:09:00 得分:0
    ?
    Top
    larger102(駱駝) ( 三級(初級)) 信譽(yù):100 2006-03-22 11:34:00 得分:0
    ?
    Top
    huyc_fly() ( 二級(初級)) 信譽(yù):100 2006-03-22 11:55:00 得分:0
    ?
    Top
    echomyf(ECHO) ( 二級(初級)) 信譽(yù):100 2006-03-22 12:42:00 得分:0
    ?
    Top
    diy8187(雞狗豬驢) ( 四級(中級)) 信譽(yù):105 2006-03-22 13:00:00 得分:0
    ?
    Top
    hyper784533() ( 一級(初級)) 信譽(yù):100 2006-03-22 13:05:00 得分:0
    ?
    posted @ 2006-03-22 15:53 xnabx 閱讀(221) | 評論 (0)編輯 收藏
    ? 問題一:
    ? 有int型數(shù)字如下,123,1234,12345,123456,1234567,12345678,123456789
    ? 求一個方法,輸出123 1,234 12,345 123,456 1,234,567 12,345,678 123,456,789

    ??處理:
    ? public void testPrint(int num) {
    ??? DecimalFormat format = new DecimalFormat("#,###");
    ??? System.out.println(format.format(num));
    ? }


    ?問題二、
    double類型如何正確的轉(zhuǎn)換為字符串類型

    處理:
    ?double d = 0.001;
    ??? DecimalFormat df1 = new DecimalFormat("#.####");
    ??? String result = df1.format(d);
    ??? System.out.println(result);
    posted @ 2006-03-22 15:53 xnabx 閱讀(902) | 評論 (2)編輯 收藏

    Singleton模式主要作用是保證在Java應(yīng)用程序中,一個類只有一個實例存在。解釋下面的代碼是怎么保證只有一個實例的?

    public class Singleton {
      private Singleton(){}
      private static Singleton instance = new Singleton();
      public static Singleton getInstance() {
      return instance;
      }
      }

    處理:

    因為構(gòu)造函數(shù)是私有的,用戶不能自己實例對象 private Singleton(){}
    而且指向這個唯一的對象的引用也是私有,只能通過getInstance方法返回對象的引用
    getInstance方法正實現(xiàn)了保證唯一對象的功能

    posted @ 2006-03-22 14:19 xnabx 閱讀(202) | 評論 (0)編輯 收藏
    上一周的周一和周日

    Calendar cl = Calendar.getInstance();
    ??cl.getTime();
    ??cl.add(cl.DAY_OF_YEAR, -cl.get(cl.DAY_OF_WEEK)+1);//get previous Sunday
    ??System.out.println(cl.get(cl.YEAR) + "-" + (cl.get(cl.MONTH)+1) + "-"
    ??+ cl.get(cl.DAY_OF_MONTH) +"week:"+(cl.get(cl.DAY_OF_WEEK)-1));
    ??
    ??cl.add(cl.DAY_OF_YEAR, -6 );?//get previous Monday
    ??System.out.println(cl.get(cl.YEAR) + "-" + (cl.get(cl.MONTH)+1) + "-"
    ??+ cl.get(cl.DAY_OF_MONTH) +"week:"+(cl.get(cl.DAY_OF_WEEK)-1));
    posted @ 2006-03-22 14:08 xnabx 閱讀(157) | 評論 (0)編輯 收藏

    用戶登陸,登陸成功后將用戶名和密碼保存到session中,然后轉(zhuǎn)到登陸成功后的頁面。
    現(xiàn)在有一個問題,如果有人看到了某一個頁面的url,可以直接在地址欄直接輸入url進(jìn)去,由于session中有用戶名和密碼,所以系統(tǒng)認(rèn)為他也是合法的用戶,如何解決?

    處理:

    一、 session是存在服務(wù)器上面的?
    session有兩種方式一個是cookies一個就是url重寫
    但是不管是哪種 都是向服務(wù)器傳達(dá)的是session的ID

    所以解決的方法就是?
    ???? 為session設(shè)置一個存活期:session.setMaxInactiveInterval(10);

    二、讓瀏覽器不再緩存
    <%
    response.setHeader("Pragma","No-cache");
    response.setHeader("Cache-Control","no-cache");
    response.setDateHeader("Expires", 0);
    %>

    posted @ 2006-03-22 09:31 xnabx 閱讀(156) | 評論 (0)編輯 收藏


    <%@ taglib uri="<%
    try{
    session.invalidate();
    }catch(Exception e){}
    String scope = "application";
    if (request.getParameter("scope") != null)
    {
    ?scope = request.getParameter("scope");
    }

    boolean refresh = false;
    if (request.getParameter("refresh") != null)
    {
    ?refresh = true;
    }

    boolean forceCacheUse = false;
    if (request.getParameter("forceCacheUse") != null)
    {
    ?forceCacheUse = true ;
    }
    %>
    <oscache:cache?? duration="40s" refresh="<%= request.getParameter("refresh") == null ? false : true %>" scope="<%= scope %>">

    // *****************************頁面部分*********************************//

    </oscache:cache>

    如interface A{..}
    這是你提供個某個部分的一個接口,然后
    public class B implements A{...}
    B是實現(xiàn)接口的一個類
    A a=new B();
    對象a的形式類型為A,實際指向一個B,可是你只能使用接口中已經(jīng)規(guī)定的方法,以后你無論怎么修改B,都不會影響到其他部分對對象a的使用

    這樣可以實現(xiàn)多態(tài),如果B和C都實現(xiàn)了接口A,那么我可以聲明一個A的對象變量,而實際的實例可能是B也可能是C
    多態(tài)----對同一個方法的調(diào)用,不同的實現(xiàn)類,有不同的響應(yīng)結(jié)果
    posted @ 2006-03-21 09:26 xnabx 閱讀(122) | 評論 (0)編輯 收藏
    new String(str.getBytes("gbk"),"utf-8")
    java中的字符串都是用unicode編碼來表示的,GBK編碼的漢字應(yīng)該是從程序外面獲得的(如數(shù)據(jù)庫中,或文本文件中), 例如從本地文本文件1.txt以字節(jié)流方式讀取,得到的字節(jié)數(shù)組buf就是以GBK編碼的字節(jié)數(shù)組,然后用GBK解碼成Unicode字符串str = new String(buf,"GBK"); 然后再編碼成
    UTF-8的字節(jié)數(shù)組str.getBytes("UTF-8"),這樣才算真正的轉(zhuǎn)換
    posted @ 2006-03-20 22:13 xnabx 閱讀(1297) | 評論 (1)編輯 收藏

    問題:
    <iframe name="I1" src="cs7.jsp" height="300" width="200"></iframe><br>
    <iframe name="I2" id="I2" src="cs8.jsp" height="300" width="200">iframe>

    如何把I1的值傳到I2里的一個input里?

    處理:
    document.getElementById("I2").src="cs8.jsp?param=p"
    然后再cs8.jsp中接受param值放到input中

    posted @ 2006-03-20 13:50 xnabx 閱讀(333) | 評論 (0)編輯 收藏

    問題:
    A.JSP如下:
    ……

    <iframe src="B.jsp" id="B" frameborder="0" border="0"></iframe>

    ……


    B.JSP如下,里面有一個C的JS方法
    ……
    <script type="text/javascript">
    function C()
    {

    }
    </script>
    ……

    請問如何在A.jsp里調(diào)用該C方法?

    處理:
    用b.document.script.c()
    跨域腳本訪問可能造成嚴(yán)重的安全問題。一些用戶禁用了跨域腳本訪問。

    posted @ 2006-03-20 13:43 xnabx 閱讀(995) | 評論 (0)編輯 收藏

    問題:<html>
    <iframe frameborder=0 width=600 height=50 marginheight=0 marginwidth=0 scrolling=no src="applytest.jsp" id="applytest"></iframe>
    <FORM? name="form1" METHOD="POST" ACTION="customer.do?command=addapplystudent"? onsubmit="return check_data()">
    <table>
    ? <tr>
    ??? <TD align="left">姓名 </TD>
    ??????? <td><input? type="text" name="cname">
    ????????? <font color="#FF0000">*</font>
    ??? </td>
    ? </tr>
    </table>
    </html>

    ///////////////////////////////////////////////////////////

    現(xiàn)在在Action里取到的學(xué)生所在地區(qū)的id總是空,我現(xiàn)在請教各位------怎么取到iframe中的某個參數(shù)的值?

    處理:
    可以通過iframe的id="applytest"來訪問其頁面的標(biāo)簽,如document.all.applytest.all.xxx來訪問其中的名為xxx的標(biāo)簽.通過再在主頁面設(shè)置hidden將其值拷貝一下就行.

    posted @ 2006-03-20 13:09 xnabx 閱讀(1248) | 評論 (0)編輯 收藏

    問題一、
    <table width="99%"? border="0" align="center" cellpadding="0" cellspacing="0">
    ? <tr>
    ??? <td colspan="2"><iframe frameborder=no?
    ???????????? marginheight=0 marginwidth=0 name=schistory scrolling=no
    ??????????? src="frame2.htm"? width=100%> </iframe></td>
    ? </tr>
    </table>

    現(xiàn)在的問題是當(dāng)frame2.htm顯示的內(nèi)容很長時,有些內(nèi)容看不到;如何做到該網(wǎng)頁隨iframe中嵌入的網(wǎng)頁內(nèi)容長度自動出現(xiàn)滾動條,并且這滾動條不是出現(xiàn)在iframe中

    處理:
    你這個屬于讓iframe的子頁面決定父頁面的高度。
    寫javascript吧。
    <script language="Javascript">
    function window.onload()
    {
    parent.document.all("mainFrame").style.height=document.body.scrollHeight+670;
    }
    </script>
    寫在iframe調(diào)用的子頁面里面
    后面的670是父頁面比子頁面高的高度

    問題二、如何動態(tài)控制IFrame的長和寬

    主頁面要放置一個IFrame用于嵌套顯示子頁面的信息,但是子頁面的數(shù)據(jù)多少不一,導(dǎo)致子頁面可能會很長或很短,要動態(tài)控制IFrame的高低隨子頁面的長短而變化。
    主頁面如下:
    <HTML>
    <HEAD>
    <TITLE> New Document </TITLE>
    </HEAD>
    <BODY >
    <TABLE>
    ??? <TR>
    ?<TD>
    ?? <iframe id="frmTest" height="100px" name="frmTest" src="in.html"></iframe>
    ?</TD>
    </TR>
    </TABLE>
    </BODY>
    </HTML>

    子頁面只需要做如下處理即可:
    在頁面的最下端添加如下JS腳本:
    <script language=javascript>
    ?window.parent.document.all("frmTest").style.height = document.body.scrollHeight + 10;
    </script>

    其中frmTest即為Main頁面的IFrame的ID。

    posted @ 2006-03-20 13:03 xnabx 閱讀(2392) | 評論 (3)編輯 收藏

    2.下面代碼的輸出是什么?一共在內(nèi)存中生成了幾個String對象?為什么?
    String s1 = “aaa”;
    String s2 = “aaa”;
    String s3 = new String(“aaa”);
    String s4 = new String(“AAA”);
    System.out.println(s1 == s2);
    System.out.println(s1 == s3);
    System.out.println(s1.equals(s3));

    3.下列程序在1處是否會有異常,如果沒有,輸出是什么?是否會運(yùn)行到2處,如果會,輸出是什么?為什么會有這樣的結(jié)果?
    public class TestClass {
    public void test1() {
    List list = new ArrayList();
    test2(list);
    System.out.println(list.size()); // 1處
    test3(list);
    System.out.println(list.size()); // 2處
    }

    public void test2(List list) {
    list = null;
    }

    public void test3(List list) {
    list.add(“aaaa”);
    }
    }

    4.請選出下面哪些描述是正確的。
    public class ClassA {
    public synchronized void a(){
    }
    public synchronized void b(){
    }
    }
    2 instances of ClassA had been instantiated obj1 and obj2.
    Which statements about thread are true?
    1)One thread is calling obj1.a(), another thread can call obj1.b().? .
    2)One thread is calling obj1.a(), another thread cannot call obj1.b().?
    3)One thread is calling obj1.a(), another thread can call obj2.b().? .
    4)One thread is calling obj1.a(), another thread cannot call obj2.b().?


    5.下面的程序輸出是什么?為什么?
    public class Parent {
    public void test(ArrayList list) {
    System.out.println("invoke parent's test method");
    }

    public static void main(String[] args) {
    Child a = new Child();
    ArrayList list = new ArrayList();
    a.test(list);
    }
    }

    class Child extends Parent {
    public void test(List list) {
    System.out.println("invoke child's test method");
    }
    }

    6.下面的程序輸出是什么?為什么?
    public class Parent {
    public void test(List list) {
    System.out.println("invoke parent's test method");
    }

    public static void main(String[] args) {
    Child a = new Child();
    ArrayList list = new ArrayList();
    a.test(list);
    }
    }

    class Child extends Parent {
    public void test(List list) {
    System.out.println("invoke child's test method");
    }
    }

    7.仔細(xì)分析下面的程序,寫出程序的輸出結(jié)果。
    public class Parent {
    {
    System.out.println("parent instance block");
    }

    public void test() {
    System.out.println("parent test method");
    }

    static {
    System.out.println("parent static block");
    }

    public Parent() {
    System.out.println("parent constructor");
    test();
    }

    public static void main(String[] args) {
    new Child();
    }
    }

    class Child extends Parent {

    private static int staticValue = 20;
    private int instanceValue = 20;

    {
    System.out.println("child instance block");
    }

    public void test() {
    System.out.println("child test method");
    System.out.println("static value is: " + staticValue);
    System.out.println("instance value is: " + instanceValue);
    }

    static {
    System.out.println("child static block");
    }

    public Child() {
    System.out.println("child constructor");
    }
    }

    8.下面程序的輸出是什么?
    public class TestException {
    public void test1() {
    int result = test2();
    System.out.println(result);
    }

    public int test2() {
    try{
    String s = null;
    s.substring(0, 1);
    return 1;
    } catch(Exception e) {
    return 2;
    } finally {
    return 3;
    }
    }

    public static void main(String[] args) {
    (new TestException()).test1();
    }
    }

    9.請寫出數(shù)據(jù)庫查詢操作的偽代碼,程序不需要通過編譯,只要思路正確,關(guān)鍵步驟不丟失就可以了。注意異常的捕獲,IO流的關(guān)閉。可能用到的類或接口有(Connection,DriverManager, Statement, PreparedStatement, ResultSet, SQLException)。

    posted @ 2006-03-19 23:12 xnabx 閱讀(145) | 評論 (0)編輯 收藏
    5.1.1·介紹

    什么是異常?在Java編程語言中,異常類定義程序中可能遇到的輕微
    的錯誤條件。可以寫代碼來處理異常并繼續(xù)程序執(zhí)行,而不是讓程序
    中斷。在程序執(zhí)行中,任何中斷正常程序流程的異常條件就是錯誤或
    ]異常。例如,發(fā)生下列情況時,會出現(xiàn)異常:
    - 想打開的文件不存在
    - 網(wǎng)絡(luò)連接中斷
    - 受控操作數(shù)超出預(yù)定范圍
    - 非常感興趣地正在裝載的類文件丟失

    在Java編程語言中,錯誤類定義被認(rèn)為是不能恢復(fù)的嚴(yán)重錯誤條件。在
    大多數(shù)情況下,當(dāng)遇到這樣的錯誤時,建議讓程序中斷。Java編程語言
    實現(xiàn)C++異常來幫助建立彈性代碼。在程序中發(fā)生錯誤時,發(fā)現(xiàn)錯誤的
    方法能拋出一個異常到其調(diào)用程序,發(fā)出已經(jīng)發(fā)生問題的信號。然后,
    調(diào)用方法捕獲拋出的異常,在可能時,再恢復(fù)回來。這個方案給程序員
    一個寫處理程序的選擇,來處理異常。通過瀏覽API,可以決定方法拋出
    的是什么樣的異常。

    5.1.2·實例

    考慮一下HelloWorld.java程序版本的簡單擴(kuò)展,它通過信息來循環(huán):
    1. public class HelloWorld {
    2. public static void main (String args[]) {
    3. int i = 0;
    4.
    5. String greetings [] = {
    6. "Hello world!",
    7. "No, I mean it!",
    8. "HELLO WORLD!!"
    9. };
    10.
    11. while (i < 4) {
    12. System.out.println (greetings[i]);
    13. i++;
    14. }
    15. }
    16. }

    正常情況下,當(dāng)異常被拋出時,在其循環(huán)被執(zhí)行四次之后,程序終止,并帶有
    錯誤信息,就象前面所示的程序那樣。
    1. c:\student\> java HelloWorld
    2. Hello world!
    3. No, I mean it!
    4. HELLO WORLD!!
    5. java.lang.ArrayIndexOutOfBoundsException: 3
    6. at HelloWorld.main(HelloWorld.java:12)

    異常處理允許程序捕獲異常,處理它們,然后繼續(xù)程序執(zhí)行。它是分層把關(guān),
    因此,錯誤情況不會介入到程序的正常流程中。特殊情況發(fā)生時,在與正常
    執(zhí)行的代碼分離的代碼塊中被處理。這就產(chǎn)生了更易識別和管理的代碼。

    5.2·異常處理

    Java編程語言提供了一個來考慮哪個異常被拋出以及如何來恢復(fù)它的機(jī)制。

    ·try和catch語句

    要處理特殊的異常,將能夠拋出異常的代碼放入try塊中,然后創(chuàng)建相應(yīng)的
    catch塊的列表,每個可以被拋出異常都有一個。如果生成的異常與catch
    中提到的相匹配,那么catch條件的塊語句就被執(zhí)行。在try塊之后,可能
    有許多catch塊,每一個都處理不同的異常。
    1. try {
    2. // code that might throw a particular exception
    3. } catch (MyExceptionType e) {
    4. // code to execute if a MyExceptionType exception is thrown
    5. } catch (Exception e) {
    6. // code to execute if a general Exception exception is thrown
    7. }

    5.2.1·調(diào)用棧機(jī)制

    如果方法中的一個語句拋出一個沒有在相應(yīng)的try/catch塊中處理的異常,
    那么這個異常就被拋出到調(diào)用方法中。如果異常也沒有在調(diào)用方法中被處理,
    它就被拋出到該方法的調(diào)用程序。這個過程要一直延續(xù)到異常被處理。
    如果異常到這時還沒被處理,它便回到main(),而且,即使main()不處理它,
    那么,該異常就異常地中斷程序。考慮這樣一種情況,在該情況中main()
    方法調(diào)用另一個方法(比如,first()),然后它調(diào)用另一個
    (比如,second())。如果在second()中發(fā)生異常,那么必須做一個檢查
    來看看該異常是否有一個catch;如果沒有,那么對調(diào)用棧(first())中的
    下一個方法進(jìn)行檢查,然后檢查下一個(main())。如果這個異常在該
    調(diào)用棧上沒有被最后一個方法處理,那么就會發(fā)生一個運(yùn)行時錯誤,
    程序終止執(zhí)行。

    5.2.2·finally語句

    finally語句定義一個總是執(zhí)行的代碼塊,而不考慮異常是否被捕獲。
    下述樣板代碼來自Frank Yellin弗蘭克葉林的白皮書《Java中的低級安全》:
    1. try {
    2. startFaucet();
    3. waterLawn();
    4. }
    5. finally {
    6. stopFaucet();
    7. }

    在前面的例子中,即使異常在打開開關(guān)或給草地澆水時發(fā)生,開關(guān)也能被關(guān)掉。
    try 后面的括號中的代碼被稱做保護(hù)碼。如果終止程序的System.exit()
    方法在保護(hù)碼內(nèi)被執(zhí)行,那么,這是finally語句不被執(zhí)行的唯一情況。
    這就暗示,控制流程能偏離正常執(zhí)行順序,比如,如果一個return語句
    被嵌入try塊內(nèi)的代碼中,那么,finally塊中的代碼應(yīng)在return前執(zhí)行。

    5.2.3·重訪前例

    下面的例子是第169頁main()方法的重寫。本程序以前的版本中產(chǎn)生的
    異常被捕獲,數(shù)組索引重新設(shè)定,使下述程序繼續(xù)運(yùn)行。
    1. public static void main (String args[]) {
    2. int i = 0;
    3. String greetings [] = {
    4. "Hello world!",
    5. "No, I mean it!",
    6. "HELLO WORLD!!"
    7. };
    8. while (i < 4) {
    9. try {
    10. System.out.println (greetings[i]);
    11. } catch (ArrayIndexOutOfBoundsException e){
    12. System.out.println( "Re-setting Index Value");
    13. i = -1;
    14. } finally {
    15. System.out.println("This is always printed");
    16. }
    17. i++;
    18. } // end while()
    19. } // end main()

    當(dāng)循環(huán)被執(zhí)行時,下述在屏幕上出現(xiàn)的信息將改變。

    1. Hello world!
    2. This is always printed
    3. No, I mean it!
    4. This is always printed
    5. HELLO WORLD!!
    6. This is always printed
    7. Re-setting Index Value
    8. This is always printed

    5.3·異常分類

    在Java編程語言中,異常有三種分類。Java.lang.Throwable類充當(dāng)所有
    對象的父類,可以使用異常處理機(jī)制將這些對象拋出并捕獲。在Throwable
    類中定義方法來檢索與異常相關(guān)的錯誤信息,并打印顯示異常發(fā)生的棧
    跟蹤信息。它有Error和Exception兩個基本子類.
    Throwable類不能使用,而使用子類異常中的一個來描述任何特殊異常。
    每個異常的目的描述如下:
    - Error表示恢復(fù)不是不可能但很困難的情況下的一種嚴(yán)重問題。比如說
    內(nèi)存溢出。不可能指望程序能處理這樣的情況。
    - RuntimeException表示一種設(shè)計或?qū)崿F(xiàn)問題。也就是說,它表示如果
    程序運(yùn)行正常,從不會發(fā)生的情況。比如,如果數(shù)組索引擴(kuò)展不超出
    數(shù)組界限,那么,ArrayIndexOutOfBoundsException異常從不會拋出。
    比如,這也適用于取消引用一個空值對象變量。因為一個正確設(shè)計和
    實現(xiàn)的程序從不出現(xiàn)這種異常,通常對它不做處理。這會導(dǎo)致一個
    運(yùn)行時信息,應(yīng)確保能采取措施更正問題,而不是將它藏到誰也不
    注意的地方。
    - 其它異常表示一種運(yùn)行時的困難,它通常由環(huán)境效果引起,可以進(jìn)行
    處理。例子包括文件未找到或無效URL異常(用戶打了一個錯誤的URL),
    如果用戶誤打了什么東西,兩者都容易出現(xiàn)。這兩者都可能因為用戶
    錯誤而出現(xiàn),這就鼓勵程序員去處理它們。

    5.4·共同異常

    Java編程語言提供幾種預(yù)定義的異常。下面是可能遇到的更具共同性的
    異常中的幾種:

    - ArithmeticException—整數(shù)被0除,運(yùn)算得出的結(jié)果。
    - int I =12 / 0;
    - NullPointerException—當(dāng)對象沒被實例化時,訪問對象的屬性或
    方法的嘗試:
    - Date d= null;
    - System.out.println(d.toString());
    - NegativeArraySizeException—創(chuàng)建帶負(fù)維數(shù)大小的數(shù)組的嘗試。
    - ArrayIndexoutofBoundsException—訪問超過數(shù)組大小范圍的一個元
    素的嘗試。
    - SecurityException—典型地被拋出到瀏覽器中,SecurityManager類將
    拋出applets的一個異常,該異常企圖做下述工作(除非明顯地得到允許):
    - 訪問一個本地文件
    - 打開主機(jī)的一個socket,這個主機(jī)與服務(wù)于applet的主機(jī)不是同一個。
    - 在運(yùn)行時環(huán)境中執(zhí)行另一個程序

    5.5·處理或聲明規(guī)則

    為了寫出健壯的代碼,Java編程語言要求,當(dāng)一個方法在棧(即,它已經(jīng)被
    調(diào)用)上發(fā)生Exception(它與Error或RuntimeException不同)時,那么,
    該方法必須決定如果出現(xiàn)問題該采取什么措施。程序員可以做滿足該要求
    的兩件事:

    第一,通過將Try{}catch(){}塊納入其代碼中,在這里捕獲給被
    命名為屬于某個超類的異常,并調(diào)用方法處理它。即使catch塊是空的,
    這也算是處理情況。
    第二,讓被調(diào)用的方法表示它將不處理異常,而且該異常將被拋回到它所
    遇到的調(diào)用方法中。它是按如下所示通過用throws子句標(biāo)記的該調(diào)用方法
    的聲明來實現(xiàn)的: public void troublesome() throws IOException
    關(guān)鍵字throws之后是所有異常的列表,方法可以拋回到它的調(diào)用程序中。
    盡管這里只顯示了一個異常,如果有成倍的可能的異常可以通過該方法
    被拋出,那么,可以使用逗號分開的列表。

    是選擇處理還是選擇聲明一個異常取決于是否給你自己或你的調(diào)用程序一個
    更合適的候選的辦法來處理異常。注—由于異常類象其它類一樣被組編到
    層次中,而且由于無論何時想要使用超類都必須使用子類, 因此,可以
    捕獲異常“組”并以相同的捕獲代碼來處理它們。例如,盡管
    IOExceptions(EOFException,FileNotFoundException等等)
    有幾種不同的類型,通過俘獲IOException,也可以捕獲
    IOException任何子類的實例。

    5.6·創(chuàng)建自己的異常

    5.6.1·介紹

    用戶定義異常是通過擴(kuò)展Exception類來創(chuàng)建的。這種異常類可以包含
    一個“普通”類所包含的任何東西。下面就是一個用戶定義異常類例子,
    它包含一個構(gòu)造函數(shù)、幾個變量以及方法:

    1. public class ServerTimedOutException extends Exception {
    2. private String reason;
    3. private int port;
    4. public ServerTimedOutException (String reason,int port){
    5. this.reason = reason;
    6. this.port = port;
    7. }
    8. public String getReason() {
    9. return reason;
    10. }
    11. public int getPort() {
    12. return port;
    13. }
    14. }

    使用語句來拋出已經(jīng)創(chuàng)建的異常:
    throw new ServerTimedOutException
    ("Could not connect", 80);

    5.6.2·實例

    考慮一個客戶服務(wù)器程序。在客戶代碼中,要與服務(wù)器連接,并希望
    服務(wù)器在5秒鐘內(nèi)響應(yīng)。如果服務(wù)器沒有響應(yīng),那么,代碼就如下所述
    拋出一個異常(如一個用戶定義的ServerTimedOutException)。

    1. public void connectMe(String serverName) throws
    ServerTimedOutException {
    2. int success;
    3. int portToConnect = 80;
    4. success = open(serverName, portToConnect);
    5. if (success == -1) {
    6. throw new ServerTimedOutException(
    7. "Could not connect", 80);
    8. }
    9. }

    要捕獲異常,使用try語句:
    1. public void findServer() {
    2. . . .
    3. try {
    4. connectMe(defaultServer);
    5. } catch(ServerTimedOutException e) {
    6. System.out.println("Server timed out, trying alternate");
    7. try {
    8. connectMe(alternateServer);
    9. } catch (ServerTimedOutException e1) {
    10. System.out.println("No server currently available");
    11. }
    12. }
    13. .. .
    注—try和catch塊可以如前例所述那樣被嵌套。

    也可能部分地處理一個異常然后也將它拋出。如:
    try {
    .....
    .....
    } catch (ServerTimedOutException e) {
    System.out.println("Error caught ");
    throw e;
    }
    posted @ 2006-03-19 22:56 xnabx 閱讀(235) | 評論 (0)編輯 收藏
    private static void getMaxdays(int year,int mon){
    ??? Calendar ca = Calendar.getInstance();
    ??? ca.clear();
    ??? ca.set(Calendar.YEAR,year);
    ??? ca.set(Calendar.MONTH,mon+1);
    ???
    ??? int max = ca.getActualMaximum(Calendar.DAY_OF_MONTH);
    ??? System.out.println(max);
    ?? }
    posted @ 2006-03-19 22:48 xnabx 閱讀(314) | 評論 (0)編輯 收藏

    abstract class和interface是Java語言中對于抽象類定義進(jìn)行支持的兩種機(jī)制,正是由于這兩種機(jī)制的存在,才賦予了Java強(qiáng)大的面向?qū)ο竽芰Α?br />接口:沒有提供任何具體實現(xiàn),可以說是一個極度抽象的類,他允許你創(chuàng)建一個能夠被向上轉(zhuǎn)型為不止一種基類型的類,以此來實現(xiàn)多重繼承。
    抽象類:包含一種或多種抽象方法的類,且可以提供具體的實現(xiàn)。定義抽象類后,其他類可以對他進(jìn)行擴(kuò)充并且通過實現(xiàn)其中的抽象方法,使用抽象類具體話。
    Java中的接口和抽象類的區(qū)別:接口中沒有屬性,而且所有的方法都是抽象的,而抽象類可以有屬性,而且可以有抽象方法,也可以有實現(xiàn)的方法。但兩者都不能被實例話。
    使用的時候,一個類可以繼承多個接口,但只能繼承一個抽象類。
    一、理解抽象類
    abstract class和interface在Java語言中都是用來進(jìn)行抽象類(本文中的抽象類并非從abstract class翻譯而來,它表示的是一個抽象體,而abstract class為Java語言中用于定義抽象類的一種方法,請讀者注意區(qū)分)定義的,那么什么是抽象類,使用抽象類能為我們帶來什么好處呢?
    在面向?qū)ο蟮母拍钪校覀冎浪械膶ο蠖际峭ㄟ^類來描繪的,但是反過來卻不是這樣。并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。抽象類往往用來表征我們在對問題領(lǐng)域進(jìn)行分析、設(shè)計中得出的抽象概念,是對一系列看上去不同,但是本質(zhì)上相同的具體概念的抽象。
    比如:如果我們進(jìn)行一個圖形編輯軟件的開發(fā),就會發(fā)現(xiàn)問題領(lǐng)域存在著圓、三角形這樣一些具體概念,它們是不同的,但是它們又都屬于形狀這樣一個概念,形狀這個概念在問題領(lǐng)域是不存在的,它就是一個抽象概念。正是因為抽象的概念在問題領(lǐng)域沒有對應(yīng)的具體概念,所以用以表征抽象概念的抽象類是不能夠?qū)嵗摹?br />在面向?qū)ο箢I(lǐng)域,抽象類主要用來進(jìn)行類型隱藏。我們可以構(gòu)造出一個固定的一組行為的抽象描述,但是這組行為卻能夠有任意個可能的具體實現(xiàn)方式。這個抽象描述就是抽象類,而這一組任意個可能的具體實現(xiàn)則表現(xiàn)為所有可能的派生類。模塊可以操作一個抽象體。由于模塊依賴于一個固定的抽象體,因此它可以是不允許修改的;同時,通過從這個抽象體派生,也可擴(kuò)展此模塊的行為功能。熟悉OCP的讀者一定知道,為了能夠?qū)崿F(xiàn)面向?qū)ο笤O(shè)計的一個最核心的原則OCP(Open-Closed Principle),抽象類是其中的關(guān)鍵所在。
    二、從語法定義層面看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可以有自己的數(shù)據(jù)成員,也可以有非abstarct的成員方法,而在interface方式的實現(xiàn)中,Demo只能夠有靜態(tài)的不能被修改的數(shù)據(jù)成員(也就是必須是static final的,不過在interface中一般不定義數(shù)據(jù)成員),所有的成員方法都是abstract的。從某種意義上說,interface是一種特殊形式的abstract class。
    從編程的角度來看,abstract class和interface都可以用來實現(xiàn)"design by contract"的思想。但是在具體的使用上面還是有一些區(qū)別的。
    首先,abstract class在Java語言中表示的是一種繼承關(guān)系,一個類只能使用一次繼承關(guān)系。但是,一個類卻可以實現(xiàn)多個interface。也許,這是Java語言的設(shè)計者在考慮Java對于多重繼承的支持方面的一種折中考慮吧。
    其次,在abstract class的定義中,我們可以賦予方法的默認(rèn)行為。但是在interface的定義中,方法卻不能擁有默認(rèn)行為,為了繞過這個限制,必須使用委托,但是這會 增加一些復(fù)雜性,有時會造成很大的麻煩。
    在抽象類中不能定義默認(rèn)行為還存在另一個比較嚴(yán)重的問題,那就是可能會造成維護(hù)上的麻煩。因為如果后來想修改類的界面(一般通過abstract class或者interface來表示)以適應(yīng)新的情況(比如,添加新的方法或者給已用的方法中添加新的參數(shù))時,就會非常的麻煩,可能要花費(fèi)很多的時間(對于派生類很多的情況,尤為如此)。但是如果界面是通過abstract class來實現(xiàn)的,那么可能就只需要修改定義在abstract class中的默認(rèn)行為就可以了。
    同樣,如果不能在抽象類中定義默認(rèn)行為,就會導(dǎo)致同樣的方法實現(xiàn)出現(xiàn)在該抽象類的每一個派生類中,違反了"one rule,one place"原則,造成代碼重復(fù),同樣不利于以后的維護(hù)。因此,在abstract class和interface間進(jìn)行選擇時要非常的小心。
    三、從設(shè)計理念層面看abstract class和interface
    上面主要從語法定義和編程的角度論述了abstract class和interface的區(qū)別,這些層面的區(qū)別是比較低層次的、非本質(zhì)的。本文將從另一個層面:abstract class和interface所反映出的設(shè)計理念,來分析一下二者的區(qū)別。作者認(rèn)為,從這個層面進(jìn)行分析才能理解二者概念的本質(zhì)所在。
    前面已經(jīng)提到過,abstarct class在Java語言中體現(xiàn)了一種繼承關(guān)系,要想使得繼承關(guān)系合理,父類和派生類之間必須存在"is a"關(guān)系,即父類和派生類在概念本質(zhì)上應(yīng)該是相同的。對于interface 來說則不然,并不要求interface的實現(xiàn)者和interface定義在概念本質(zhì)上是一致的,僅僅是實現(xiàn)了interface定義的契約而已。為了使論述便于理解,下面將通過一個簡單的實例進(jìn)行說明。
    考慮這樣一個例子,假設(shè)在我們的問題領(lǐng)域中有一個關(guān)于Door的抽象概念,該Door具有執(zhí)行兩個動作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。看起來好像使用abstract class和interface沒有大的區(qū)別。
    如果現(xiàn)在要求Door還要具有報警的功能。我們該如何設(shè)計針對該例子的類結(jié)構(gòu)呢(在本例中,主要是為了展示abstract class和interface反映在設(shè)計理念上的區(qū)別,其他方面無關(guān)的問題都做了簡化或者忽略)下面將羅列出可能的解決方案,并從設(shè)計理念層面對這些不同的方案進(jìn)行分析。
    解決方案一:
    簡單的在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() { … }


    這種方法違反了面向?qū)ο笤O(shè)計中的一個核心原則ISP(Interface Segregation Priciple),在Door的定義中把Door概念本身固有的行為方法和另外一個概念"報警器"的行為方法混在了一起。這樣引起的一個問題是那些僅僅依賴于Door這個概念的模塊會因為"報警器"這個概念的改變(比如:修改alarm方法的參數(shù))而改變,反之依然。
    解決方案二:
    既然open、close和alarm屬于兩個不同的概念,根據(jù)ISP原則應(yīng)該把它們分別定義在代表這兩個概念的抽象類中。定義方式有:這兩個概念都使用abstract class方式定義;兩個概念都使用interface方式定義;一個概念使用abstract class方式定義,另一個概念使用interface方式定義。
    顯然,由于Java語言不支持多重繼承,所以兩個概念都使用abstract class方式定義是不可行的。后面兩種方式都是可行的,但是對于它們的選擇卻反映出對于問題領(lǐng)域中的概念本質(zhì)的理解、對于設(shè)計意圖的反映是否正確、合理。我們一一來分析、說明。
    如果兩個概念都使用interface方式來定義,那么就反映出兩個問題:
    1、我們可能沒有理解清楚問題領(lǐng)域,AlarmDoor在概念本質(zhì)上到底是Door還是報警器?
    2、如果我們對于問題領(lǐng)域的理解沒有問題,比如:我們通過對于問題領(lǐng)域的分析發(fā)現(xiàn)AlarmDoor在概念本質(zhì)上和Door是一致的,那么我們在實現(xiàn)時就沒有能夠正確的揭示我們的設(shè)計意圖,因為在這兩個概念的定義上(均使用interface方式定義)反映不出上述含義。
    如果我們對于問題領(lǐng)域的理解是:AlarmDoor在概念本質(zhì)上是Door,同時它有具有報警的功能。我們該如何來設(shè)計、實現(xiàn)來明確的反映出我們的意思呢?前面已經(jīng)說過,abstract class在Java語言中表示一種繼承關(guān)系,而繼承關(guān)系在本質(zhì)上是"is a"關(guān)系。所以對于Door這個概念,我們應(yīng)該使用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() { … }
    }


    這種實現(xiàn)方式基本上能夠明確的反映出我們對于問題領(lǐng)域的理解,正確的揭示我們的設(shè)計意圖。其實abstract class表示的是"is a"關(guān)系,interface表示的是"like a"關(guān)系,大家在選擇時可以作為一個依據(jù),當(dāng)然這是建立在對問題領(lǐng)域的理解上的,比如:如果我們認(rèn)為AlarmDoor在概念本質(zhì)上是報警器,同時又具有Door的功能,那么上述的定義方式就要反過來了。
    abstract class和interface是Java語言中的兩種定義抽象類的方式,它們之間有很大的相似性。但是對于它們的選擇卻又往往反映出對于問題領(lǐng)域中的概念本質(zhì)的理解、對于設(shè)計意圖的反映是否正確、合理,因為它們表現(xiàn)了概念間的不同的關(guān)系(雖然都能夠?qū)崿F(xiàn)需求的功能)。這其實也是語言的一種的慣用法,希望讀者朋友能夠細(xì)細(xì)體會

    posted @ 2006-03-19 15:41 xnabx 閱讀(204) | 評論 (0)編輯 收藏
    WebServices 是部署在WEB上的組件和對象!
    ? 它具有以下幾點特征:
    ?? 1. 高度的耦合性.就是移植性還不錯,相互依賴不強(qiáng) .
    ?? 2. 高度的集成性.
    ?? 3. 完好的封狀性. 就是我們只可以看到他想讓你看到的東西 呵呵!
    ?? 4. 使用標(biāo)準(zhǔn)協(xié)議規(guī)范.
    posted @ 2006-03-19 12:05 xnabx 閱讀(212) | 評論 (0)編輯 收藏
    對synchronized(this)的一些理解
    ?

    一、當(dāng)兩個并發(fā)線程訪問同一個對象object中的這個synchronized(this)同步代碼塊時,一個時間內(nèi)只能有一個線程得到執(zhí)行。另一個線程必須等待當(dāng)前線程執(zhí)行完這個代碼塊以后才能執(zhí)行該代碼塊。

    二、然而,當(dāng)一個線程訪問object的一個synchronized(this)同步代碼塊時,另一個線程仍然可以訪問該object中的非synchronized(this)同步代碼塊。

    三、尤其關(guān)鍵的是,當(dāng)一個線程訪問object的一個synchronized(this)同步代碼塊時,其他線程對object中所有其它synchronized(this)同步代碼塊的訪問將被阻塞。

    四、第三個例子同樣適用其它同步代碼塊。也就是說,當(dāng)一個線程訪問object的一個synchronized(this)同步代碼塊時,它就獲得了這個object的對象鎖。結(jié)果,其它線程對該object對象所有同步代碼部分的訪問都被暫時阻塞。

    五、以上規(guī)則對其它對象鎖同樣適用.

    posted @ 2006-03-18 00:32 xnabx 閱讀(192) | 評論 (0)編輯 收藏
    全面認(rèn)識JAVA
    作者:unknown 更新時間:2005-04-07 ?
    ?
    作SCJP培訓(xùn)已經(jīng)有一段時間了,到我這學(xué)習(xí)的有在校的大學(xué)生,也有在職的開發(fā)人員。通常這些學(xué)員此前都對Java已有一些了解,但普遍對Java缺乏總體的認(rèn)識。于是學(xué)員總是問,Java應(yīng)該怎么學(xué)?Java能做什么?什么是Applet?什么是Servlet、Jsp、EJB?還有Webspere、Weblogic又是做什么的等等。之所以學(xué)員會有這些疑問,是因為大家普遍對Java相關(guān)概念聽說的太多而了解的又相對少的緣故。

    學(xué)通Java語言需要一個過程,所有Java相關(guān)的概念都會在學(xué)習(xí)的過程中逐漸變得清昕。這個過程的開始就是要先學(xué)會標(biāo)準(zhǔn)的Java技術(shù)(J2SE),然后是學(xué)Java的簡單Web運(yùn)用,然后分布式運(yùn)用,再以后對Java的移動技術(shù)運(yùn)用就很容易理解了。

    以下是Java標(biāo)準(zhǔn)技術(shù)的一些要點:

    一、Java的跨平臺性,即一次編譯到處運(yùn)行

    簡單地說Java的跨平臺性就是指,編譯后的Java程序可直接在不同的平臺上運(yùn)行而不用重新編譯,這一特性使得Java隨著Web應(yīng)用的普及而迅速普及起來。而Java的跨平臺性是如何實現(xiàn)的呢?這就要理解Java虛擬機(jī)和字節(jié)碼的概念。

      實際上,編譯后的Java代碼并不是傳統(tǒng)的二進(jìn)制代碼(如Windows下的.exe文件),而是Java字節(jié)碼,這種字節(jié)碼文件是不能直接在操作系統(tǒng)上執(zhí)行的。要想在一個操作系統(tǒng)上運(yùn)行一個Java程序必須有一個中間環(huán)節(jié)來負(fù)責(zé)將Java字節(jié)碼解釋成二進(jìn)制碼,這個中間環(huán)節(jié)就是Java虛擬機(jī)(簡稱JVM)。由于目前大多數(shù)操作系統(tǒng)已經(jīng)實現(xiàn)了JVM,所以Java輕松實現(xiàn)跨平臺性。

      二、面象對象技術(shù)

      Java全面支持面象對象技術(shù),這體現(xiàn)在Class(類)是Java程序構(gòu)成的基本單元,一個Java程序通常由許多Class組成,而且這些Class還會有一定的繼承關(guān)系,Java支持Class的單繼承,從而使類之間的繼承關(guān)系更明確。繼承的結(jié)果產(chǎn)生類的多態(tài)性,類的多態(tài)本質(zhì)上講就是可以用父類的引用訪問繼承類的實現(xiàn)(子類對象),類的這種多態(tài)性最終形成了組件對象模型的基礎(chǔ),即通過接口(父類)訪問實現(xiàn)(子類)。

      三、Java中的I/O操作

      Java中以字節(jié)流(InputStream和OutputStream)、節(jié)符流(Reader和Writer)來分別讀寫二進(jìn)制數(shù)據(jù)和字符數(shù)據(jù),使用非常簡單有效。Java類庫中的File類不僅提供文件操作而且還包含文件夾操作,如下面這幾行代碼可以列出C盤根目錄下的所有文件:

    File f=new File("c://");
    String [] m_dir= f.list();
    for(int i=0;i<m_dir.length;i++)
    System.out.println(m_dir[i]);

    四、Java中的圖形及事件處理

    可以用awt包或swing包的Java類來進(jìn)行大部分的Java圖形界面設(shè)計,下面的幾行代碼將產(chǎn)生一個200*200像素的窗體:

    Frame f=new Frame("Welcome");
    f.setSize(200,200);
    f.setVisible(true);

    默認(rèn)情況下,F(xiàn)rame窗體的關(guān)閉按鈕不起作用,這也是Java初學(xué)者迷惑的地方。為了使用戶按下關(guān)閉按鈕時能關(guān)閉Frame窗體,需要讓這個窗體響應(yīng)一個WindowEvent事件,具體的做法就是給這個窗體添加一個事件監(jiān)聽器對象,這個事件監(jiān)聽器就是WindowListener接口的實現(xiàn)。在上面的代碼中插入如下代碼就可以關(guān)閉窗體:

    f.addWindowListener(new WindowAdapter(){
    ??public void windowClosing(WindowEvent e){
    System.exit(0);
    ??}
    }

    這里用到一個無名內(nèi)部類,無名內(nèi)部類是Java中內(nèi)部類的一種靈活運(yùn)用方式。

    五、Java中線程及同步控制

    線程概念的引入是為了實現(xiàn)并行處理,從而提高程序的效率。Java中的線程實現(xiàn)非常簡單,可以用兩種方式來創(chuàng)建線程,一種是實現(xiàn)Runnable接口,另一種是繼承Thread類重寫run()方法。兩種方式唯一的不同就是前者保留了繼承一個類的可能(因為Java只支持類的單繼承,但接口沒有此限制)。

      永遠(yuǎn)都用start()方法來啟動一個線程,線程類中的run()可以被直接調(diào)用,但決不是啟動一個線程,二者有著本質(zhì)的區(qū)別。

      用同步控制關(guān)鍵字synchronized來保護(hù)線程敏感數(shù)據(jù),synchronized塊中的內(nèi)容可以保證同一時刻只能被一個線程訪問,所以其中的數(shù)據(jù)是線程安全的。

      用Object類中的wait()和notify()方法可以實現(xiàn)線程間交互,但要記住wait()和notify()方法只有發(fā)生在同一個對象上才能真正實現(xiàn)線程間交互。被某一對象wait()方法阻塞的線程需要另外一個調(diào)用了同一對象notify()的線程干預(yù)才能恢復(fù)運(yùn)行。notify()方法一次喚醒一個被wait()方法阻塞的線程,notifyAll()方法可以一次喚醒所有被wait()方法阻塞的線程。

      六、Java本地方法(native方法)的實現(xiàn)

      Java不是完美的,Java的不足除了體現(xiàn)在運(yùn)行速度上要比傳統(tǒng)的C++慢許多之外,Java無法直接訪問到操作系統(tǒng)底層(如系統(tǒng)硬件等),為此Java使用native方法來擴(kuò)展Java程序的功能。

      可以將native方法比作Java程序同C程序的接口,其實現(xiàn)步驟:

      1、在Java中聲明native()方法,然后編譯;
      2、用javah產(chǎn)生一個.h文件;
      3、寫一個.cpp文件實現(xiàn)native導(dǎo)出方法,其中需要包含第二步產(chǎn)生的.h文件(注意其中又包含了JDK帶的jni.h文件);
      4、將第三步的.cpp文件編譯成動態(tài)鏈接庫文件;
      5、在Java中用System.loadLibrary()方法加載第四步產(chǎn)生的動態(tài)鏈接庫文件,這個native()方法就可以在Java中被訪問了。

      上述所提及的一些Java技術(shù)具有一定的普遍性,它們基本上是在Java各個方面的運(yùn)用中都需要掌握的術(shù)。實際上Java的運(yùn)用非常廣泛,而且每個方面都需要遵循不同的規(guī)范。以下是對Java應(yīng)用的簡要介紹。

    (一)理解Java SDK的三個版本:

    Java SDK Micro Edition (J2ME)

    用于開發(fā)掌上電腦、手機(jī)等移動通信設(shè)備上使用的應(yīng)用程序。并不是所有的移動設(shè)備都支持Java,只有具備J2ME運(yùn)行環(huán)境(JVM+J2ME API)的設(shè)備才能運(yùn)行Java程序。J2ME的集成開發(fā)工具(通常都有帶有一些訪真器)有 Sun 的J2ME Wireless Toolkit 、IBM的Visul Age Micro Edition 等。

    Java SDK Standard Edition(J2SE)

    主要用于開發(fā)一般臺式機(jī)應(yīng)用程序。我們平時所說的JDK就指J2SE,而我們學(xué)Java就是從學(xué)習(xí)J2SE開始的。

    Java SDK Enterprise Edition (J2EE)

    用于開發(fā)分布式的企業(yè)級大型應(yīng)用程序。其中的核心是Entetprise Java Beans(EJB,分布式Java組件)的開發(fā)。

    (二)Java小程序 (Applet)

    Java小程序是一個繼承了Applet類并重寫了init()、paint()、stop()等方法的的Java類,它被布署在Web服務(wù)器(如IIS)上,當(dāng)客戶端請求Web頁時,瀏覽器從Web服務(wù)器上將其下載到本地客戶端,然后,瀏覽器創(chuàng)建該Applet類的實例并調(diào)用其init()方法,從安全角度考慮,Applet沒有訪問本地文件的權(quán)限。由于Applet是被瀏覽器執(zhí)行的,所以Applet不需要一個main()方法。實際上,除了Java Application之外,所有其它Java應(yīng)用都不需要一個main()方法。

    (三)服務(wù)器端Java小程序 (Servlet)

    Servlet也是一個Java類,和Applet形成對比,Servlet是運(yùn)行于服務(wù)器端的Java小程序,而且Servlet需要一個單獨(dú)的Web服務(wù)器(如Tomcat)做容器。除此之外,Servlet中用到的一些類(如HttpServlet)并不包含在J2SE API中,所以需要將Servlet.jar(在Tomcat的common\lib文件夾下)加到環(huán)境變量中去。下面是一個簡單的Servlet例子:

    public class Myservlet extends HttpServlet{

    ??public void doGet(HttpServletRequest request,HttpServletResponse response)
    {
    ??try{
    response.setContentType("text/html");
    PrintWriter out=response.getWriter();
    out.println("<html>");
    out.println("<body>");
    out.println("Hello world");
    out.println("</body>");
    out.println("</html>");
    ??}catch(IOException e){}
    }
    }

    將這個Class文件編譯后放至Tomcat\webapps\examples\WEB-INF\classes下,然后在瀏覽器地址欄里輸入http://127.0.0.1:8080/examples/servlet/Myservlet即可看到 Hello world出現(xiàn)在瀏覽器中。

    (四)Java Server Page (JSP)

    同Servlet相似的是,JSP運(yùn)行于Web服務(wù)器端,并且也需要Tomcat之類的容器。不同的是,由于JSP是將Java代碼嵌在html標(biāo)記里(同ASP一樣用<% ...%>),JSP的界面設(shè)計同后臺開發(fā)人員的工作可以有效分離。可以想像讓開發(fā)人員用Servlet寫一個花捎的Web頁面有多困難,所以JSP+Servlet混合Web應(yīng)用是比較理想的選擇。

    看起來JSP同ASP的實現(xiàn)機(jī)制大同小異,其實也存在著本質(zhì)的區(qū)別。所有的ASP頁面都是解釋運(yùn)行的,而JSP頁在第一次被請求時會被編譯,再以后的客戶請求都是直接運(yùn)行服務(wù)器上的.class文件(在Tomcat的Work文件夾下),所以JSP要比ASP速度上快許多。

    (五)Java Beans

    Java Bean 是可復(fù)用的組件,對Java Bean并沒有嚴(yán)格的規(guī)范,理論上講,任何一個Java類都可以是一個Bean。但通常情況下,由于Java Bean是被容器所創(chuàng)建(如Tomcat)的,所以Java Bean應(yīng)具有一個無參的構(gòu)造器,另外,通常Java Bean還要實現(xiàn)Serializable接口用于實現(xiàn)Bean的持久性。

    (六)Enterprise Java Beans (EJB)

    Java Bean實際上相當(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ī))。但EJB必須被布署在諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問真正的EJB組件,而是通過其容器訪問。EJB容器是EJB組件的代理,EJB組件由容器所創(chuàng)建和管理。客戶通過容器來訪問真正的EJB組件。

    這種模型很像COM+管理器,其實EJB容器正是起到COM+管理器的作用,只是EJB組件相對COM組件來說更易用、更安全。

    總的說來,Java作為面象對象技術(shù)的一個代表,在當(dāng)今商業(yè)應(yīng)用中更容易開發(fā)出高效的、多層的分布式應(yīng)用程序,而且,由于Java技術(shù)有很強(qiáng)的健壯性和易用性,加上同UML應(yīng)用的結(jié)合,開發(fā)一個商業(yè)應(yīng)用軟件的周期會大大縮短,所以Java會有不錯的前景。
    posted @ 2006-03-18 00:29 xnabx 閱讀(129) | 評論 (0)編輯 收藏
    Java學(xué)習(xí)過程的一些重點
    ?
    ?
    Java學(xué)習(xí)過程的一些重點

      主要說說Java的幾大塊吧,無法說得很細(xì),因為其實每一塊拿出來都能說很多,我就說一下這幾塊學(xué)習(xí)的時候的重點或者應(yīng)該注意的東西。



    數(shù)值類型:

      雖然是面向?qū)ο蟮恼Z言,但是在使用上數(shù)值類型還是必不可少的,如果在C的學(xué)習(xí)中已經(jīng)掌握了C的數(shù)值計算和轉(zhuǎn)換規(guī)則,那我想這里應(yīng)該沒有什么問題,只有兩點需要注意:1、14.0這樣的浮點常量被認(rèn)為是double型,只有加上f后綴才是float型的;2、整數(shù)常量說起來被認(rèn)為是int型,但是在編譯時,可以認(rèn)為編譯器將其看作能表示該數(shù)的最小數(shù)值,因此byte b = 100;不會報錯。



    引用類型:

      我也是從C/C++轉(zhuǎn)過來的,其實所謂引用類型在C++中已有體現(xiàn),就是傳參的時候有一種引用類型,從C來考慮,它就是一個指針,只不過,我們不能對它進(jìn)行指針上的硬操作。所以這里的重點是:1、Java里所有的對象都是在堆中生成的,所以需要類似指針的東西指向它,那就是引用;2、我們通過引用操作的是引用所指向的對象,除了賦值操作外,應(yīng)該就沒有什么操作是針對引用本身的了,這一點是C的指針與Java的引用區(qū)別所在。



    類和對象:

      這是一個大塊,有很多東西,不展開講了,就說幾個重點:1、類方法、類屬性與成員方法、成員屬性在加載、初始化、使用上的異同;2、在構(gòu)造函數(shù)中,this()和super()的用法;3、子類的加載過程、初始化過程和構(gòu)造過程;4、方法的重載和覆寫;5、覆寫所引出的多態(tài)問題。(注意:多態(tài)之應(yīng)用在方法上,對屬性沒有作用)

    函數(shù)調(diào)用的參數(shù)傳遞:

      如果把引用類型所記錄的地址值,就看作是引用類型變量的值的話,那么,Java的所有方法調(diào)用的時候,都是采用的值傳遞??數(shù)值類型傳數(shù)值,引用類型傳地址。



    IO流:

      與C比起來,Java的輸入輸出,尤其是輸入是非常麻煩的,也許是因為出于面向?qū)ο蟮目紤]吧?不知道。Java提供了很多的IO流,但是我們并不必將各種IO都搞清楚,我們只需要了解字節(jié)流與字符流各有什么功能,字符流是如何在字節(jié)流之上構(gòu)造的,幾乎所有的字符流構(gòu)造的時候都是建立在一個已有的字節(jié)流的基礎(chǔ)上的,并且它的這種設(shè)計使得我們可以像套管子一樣,將IO流一節(jié)一節(jié)套起來,直到得到我們想使用的IO對象(例:BufferedReader的使用)。在我們以后使用的時候,我們可以再去查API,我覺得主要要看的幾個類是:FileReader、FileWriter、BufferedReader,再配合上System.out對象,對于文本的輸入、輸出來說,就足夠用了,至于其他的,我覺得不考試的話,沒有必要看那么多,用的時候再看了。(我使用Java一年半來,基本上就在使用BufferedReader和System.out)



    容器:

      個人認(rèn)為,這是Java編程的一大利器,我最愛用的類是:ArrayList(List)作為可變長數(shù)組、HashMap(Map)用來建立查找表,Set我很少用,只在HashMap的使用中連帶用過一些。通過對這兩個類的熟悉,能夠?qū)ist、Set和Map三大類的基本用法掌握。另外它的幾個輔助類要掌握:Iterator和Collections。Collections類提供容器的一些通用工具,比如排序。而說到排序,就牽扯出了比較器:Comparator。能夠熟練使用Comparator類,可以讓你為自己的需求和自己的類定制排序方案。



    AWT和SWING:

      個人認(rèn)為,Java在圖形界面的制作上有著非常好的封裝性,我以前曾經(jīng)試圖學(xué)過MFC,MFC在生成圖形界面的時候會幫助你生成一些代碼,然后讓你在這些代碼的指定位置添加代碼以實現(xiàn)功能,我這個人有個習(xí)慣,如果讓我看到了一些東西,那么我不搞清除為什么這么寫,就不會往下走,看到那許多代碼,自然就想弄清楚那些是什么,結(jié)果引出來好多知識,后來我才知道其中有些是調(diào)用WinAPI,結(jié)果我到現(xiàn)在還是不會用MFC。這里并不是貶低MFC,我相信MFC有其過人之處,只不過個人認(rèn)為它的封裝性做得不好,暴露出了太多東西,也許能夠提高靈活性,不過,可能我跟它無緣:(。在這方面Java就做得不錯,給你一個類,你用就是了,它將圖形界面的低層實現(xiàn)隱藏的很好,將其作為一個對象給你,而你只需要在這個對象上修修改改,挺方便的。

      作為初學(xué)者,我覺得AWT的重點在于它的幾個Listener的用法,還有布局格式,然后就是那許多的Component的用處和用法。(不過,我覺得,等到用的時候再去找合適的Component進(jìn)行學(xué)習(xí)應(yīng)該也不算太遲 ^_^)

      不過,因為我個人使用的原因,所以至今AWT和SWING都用得很少,所以這方面也就不便多說了,抱歉。寫這些并不是告訴大家怎么解決問題,因為每一個都有很多可寫,只是希望能給初學(xué)者一點參考,希望能夠幫助初學(xué)者們有的放矢地看書。
    posted @ 2006-03-18 00:26 xnabx 閱讀(164) | 評論 (0)編輯 收藏
    JBuilder 9 常見快捷鍵
    ?
    ?

    1.工作區(qū): (顯隱)

    項目面板:ctrl + Alt + p (Project)
    設(shè)計面板: ctrl + Alt + c (content)
    結(jié)構(gòu)面板: ctrl + Alt + s (Structure)
    信息面板: ctrl + Alt + M (Message)
    狀態(tài)面板: ctrl + Alt + Z


    2.主面板:(代碼面板和設(shè)計面板)

    激活代碼模塊: ctrl + J (@1)
    參數(shù)提示信息的激活: ctrl + shift + H
    打開查詢、替換窗口: ctrl + F
    類的查詢: ctrl + -


    3.F 鍵的用法

    F1: 幫助快捷
    F4: 運(yùn)行多行
    F5: 加入斷點
    F7: 當(dāng)遇到方法時會運(yùn)行方法內(nèi)的代碼
    F8: 逐步運(yùn)行代碼
    F12: 代碼面板和設(shè)計面板切換


    4. Shift 鍵的用法

    添加多個相同組件: 按shift鍵在選項上選取組件,把組件添加到窗口即可
    調(diào)整組件間間隔和對齊: 假設(shè)有組件JPanel 1/2/3;(要達(dá)到3個組件寬度相同,組件間隔相等,并且都是依據(jù)JPanel1左對齊),按shift鍵,用鼠標(biāo)選中需要調(diào)整的組件,(第一個選中的組件是其他的基準(zhǔn))然后右鍵。


    5: codeInsight 和 Codetemplates
    MemberInsight -- 根據(jù)當(dāng)前的代碼提示可用的類成員或方法(說明)
    ParameterInsight -- 提示當(dāng)前的方法需要使用的參數(shù)
    SymbolInsigh -- 查看當(dāng)前的變量、方法或者類的愿代碼。

    MemberInsight: ctrl + space 或 ctrl + H
    ParameterInsight: ctrl + shift + space 或 ctrl + shift + H
    SymbolInsight: ctrl + Enter 或 Alt + shift + H
    ClassInsight : ctrl + alt + space 或 ctrl + alt + H




    注: (@1):使用代碼功能:(ctrl + J)
    1、 在想要輸入代碼的位置輸入代碼摸板名,然后按 ctrl + J(開發(fā)人員可以用主菜單上的Tools/Editor/Templates命令來查看代碼摸板的名字)
    2、把光標(biāo)定位于想要輸入代碼的位置,然后按ctrl + J

    posted @ 2006-03-18 00:23 xnabx 閱讀(173) | 評論 (0)編輯 收藏
    1.得到當(dāng)前程序文件的絕對路徑:this.getClass().getResource(this.getClass().getName()+".java").getPath()
    posted @ 2006-03-17 23:59 xnabx 閱讀(199) | 評論 (0)編輯 收藏

    關(guān)于軟件優(yōu)化,硬件升級方面的:

    至強(qiáng)64位雙CPU
    2G內(nèi)存 DDR2 533

    tomcat5.5默認(rèn)配置
    java5.0默認(rèn)配置
    mysql5.0默認(rèn)配置

    帶寬為10M獨(dú)享.
    如何改變軟件方面的配置要求。優(yōu)化方面的資料。硬件方面要升級哪些? 以達(dá)到支持大約在線用戶為最高2000人。

    處理:
    ???????2000 人在線,每秒鐘請求數(shù)應(yīng)該在幾百次或者更低些的程度,并發(fā)數(shù)不會超過100(平均10妙請求一次),使用普通的 PC 機(jī),每秒鐘也能夠處理上百次的請求;
    ???????緩存優(yōu)化:解決性能問題首先想到的就是緩存,在 Web 應(yīng)用中有很多緩存的方式,可以緩存到 Web 層的 servletContext 中,也可以緩存到業(yè)務(wù)層中,甚至可以在數(shù)據(jù)庫中建立冗余。而生成靜態(tài)頁面是一種極端的做法,一般來說會增加復(fù)雜性,同時可能會對靈活性和可維護(hù)性造成很大傷害。緩存的要點在于命中率,命中率低的東西不應(yīng)該緩存,除非對內(nèi)存的價格不做考慮。總結(jié)起來設(shè)計上就兩句話,使用 N 層結(jié)構(gòu),合理緩存。根據(jù)程序的需要,適當(dāng)是使用緩存機(jī)制;
    ???????程序進(jìn)行優(yōu)化方法,比如:每次查找部分記錄,而不是全部查出來,這樣既可以減輕服務(wù)器的負(fù)擔(dān),也可以減少網(wǎng)絡(luò)傳輸量; 對于系統(tǒng)中的數(shù)據(jù)庫連接一定要進(jìn)行妥善的處理; 對需要用 scrchrnozied 的地方要用,但是有些地方可以不用同步化的,這個對速度影響也很大;從代碼入手,優(yōu)化程序,在數(shù)據(jù)持久化上進(jìn)行改進(jìn),采用成熟的庫訪問對象(Data Access Object)設(shè)計模式也會節(jié)省你的服務(wù)器開銷。
    ???????硬件升級:硬件方面還不行,硬盤最好搞陣列,還可以再來一個服務(wù)器,弄個負(fù)載均衡,由兩個服務(wù)器來處理用戶的請求,apache必然是要用到的,他將擋在tomcat前處理http請求。
    ???????注意:在硬件足夠強(qiáng)大的時候,將 web 與 db 分兩臺服務(wù)器來做,只會降低效率,因為網(wǎng)絡(luò)編組的成本要比本地內(nèi)存中的復(fù)制高幾個數(shù)量級。同樣道理,負(fù)載均衡也只會導(dǎo)致更復(fù)雜的結(jié)構(gòu),會引起更多的問題,并產(chǎn)生更低于下的效率。將一個應(yīng)用分布于多臺機(jī)器的唯一理由,就是由于一臺機(jī)器根本頂不住,不得不分。
    ???????環(huán)境優(yōu)化:調(diào)Tomcat、JVM的Heap大小等參數(shù)做一些優(yōu)化, Tomcat的虛擬內(nèi)存管理有最大值限制,可以并發(fā)運(yùn)行多個Tomcat來均衡負(fù)載,tomcat5.5默認(rèn)配置? ==>改了JAVA_OPTS沒有?開大內(nèi)存 既java_opts= -Xms1024m -Xmx1024m ;? java5.0默認(rèn)配置??? ==>升級一下到最大的小版本6.0?升級處理
    ????? 系統(tǒng)內(nèi)存測試:
    ???? (1)自己測試:參考tomcat,jvm,mysql優(yōu)化方面的資料。測試如下操作出錯:
    C:\>java -Xms536870932 -Xmx536870912
    Error occurred during initialization of VM
    Incompatible initial and maximum heap sizes specified至強(qiáng)64位雙CPU,原則上面來說64位的CPU應(yīng)當(dāng)可以用到無限大的內(nèi)存了,也還是理論上的了。可以java -Xmx2000M -version這樣一路加上去試試看你的可以加到多大。
    ???? (2)工具測試:? 壓力測試:對應(yīng)用系統(tǒng)進(jìn)行性能采樣于監(jiān)控,(Wily有一套產(chǎn)品可以在運(yùn)行期進(jìn)行調(diào)優(yōu),但我沒有用過),我用的P6Spy,加MS的那個壓力測試工具,也有D用LoadRunner來跑一跑,在SQL語句這個地方有太多的名堂可做了。
    ?????? 建議軟件方面:
    ?? ??? a、軟件配置 Apache2.2.0 + mod_ajp + jrockit-R26.0.0-jdk1.5.0_04+? Tomcat5.5.15 (啟多個)+apr1.2.2 .
    ?????? b、內(nèi)存建議4g以上 。 tomcat的內(nèi)存參數(shù)使用 set JAVA_OPTS=%JAVA_OPTS%-Xms1024m -Xmx1024m? (內(nèi)存2g的話,建議set JAVA_OPTS=%JAVA_OPTS%-Xms512m -Xmx512m).
    ????? c、tomcat5.5版本的性能已經(jīng)大幅度提高了。


    ?????
    ???

    posted @ 2006-03-17 23:29 xnabx 閱讀(437) | 評論 (0)編輯 收藏

    今天遇到個以前使用Struts沒有注意的地方。
    現(xiàn)象:
    ?? 在actionForward配置文件里面定義
    ???<forward name="success" path="/Catalog.jsp" redirect="true"/>

    ?? 當(dāng)在提交頁面里面request.setAttbriute("msg","處理成功");
    ?? 提交后在Catalog.jsp 用request.getAttbriute("msg");居然為空,原因是設(shè)置了redirect="true"

    下例舉例說明了redirect屬性的用法:

    <forward name="success" path="/Catalog.jsp" redirect="true"/>

    如果 redirect=true, URL 建立如 / contextPath / path 因為 HttpServletResponse.sendRedirect(…) 中解釋 URL 采用 ”/” 開頭相對于 servlet 容器根目錄。

    如果 redirect=false, URI 建立如 / path 因為 ServletContext.getRequestDisptacher(…) 采用虛擬目錄相關(guān) URL

    posted @ 2006-03-14 18:04 xnabx 閱讀(1351) | 評論 (0)編輯 收藏

    繁重

    posted @ 2006-03-14 15:37 xnabx 閱讀(167) | 評論 (0)編輯 收藏
    主站蜘蛛池模板: 在线免费视频一区| 国产精品亚洲专区在线观看| 搜日本一区二区三区免费高清视频| 日本XXX黄区免费看| 亚洲欧洲免费视频| 91免费在线视频| 亚洲精品网站在线观看不卡无广告 | 久久亚洲AV成人无码电影| 中文在线观看国语高清免费| 九月婷婷亚洲综合在线| 亚洲色大成网站www尤物| 国产精品久久久久免费a∨| 亚洲欧洲日本天天堂在线观看| 四虎影视在线影院在线观看免费视频| 亚洲精品乱码久久久久久按摩| 国产97视频人人做人人爱免费| 亚洲国产精品国产自在在线| 在线精品自拍亚洲第一区| 在线观看免费国产视频| 亚洲av无码专区国产不乱码| 在线观看免费a∨网站| 亚洲综合色一区二区三区| 啦啦啦高清视频在线观看免费 | 免费高清小黄站在线观看| 亚洲人成77777在线播放网站不卡| 国产成人福利免费视频| 2022年亚洲午夜一区二区福利 | 日本人护士免费xxxx视频| 亚洲精品国产第一综合99久久| 在线免费观看中文字幕| 亚洲精品人成网线在线播放va| 日韩电影免费在线| 青草青草视频2免费观看| 亚洲成a人一区二区三区| 免费国产在线精品一区| 亚洲人成人网站在线观看| 国产精品美女免费视频观看| 亚洲深深色噜噜狠狠爱网站| 国色精品va在线观看免费视频 | 国产亚洲欧洲Aⅴ综合一区| 久久99精品免费一区二区|