隨筆-61  評(píng)論-13  文章-19  trackbacks-0
            2006年3月14日
               摘要:   閱讀全文
          posted @ 2010-02-04 15:30 xnabx 閱讀(1618) | 評(píng)論 (1)編輯 收藏
               摘要:   閱讀全文
          posted @ 2010-01-25 11:10 xnabx 閱讀(1035) | 評(píng)論 (1)編輯 收藏
               摘要:   閱讀全文
          posted @ 2010-01-21 09:52 xnabx 閱讀(1729) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2010-01-15 10:10 xnabx 閱讀(1413) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2010-01-15 09:57 xnabx 閱讀(341) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2009-12-04 11:45 xnabx 閱讀(609) | 評(píng)論 (3)編輯 收藏
               摘要:   閱讀全文
          posted @ 2009-12-03 15:26 xnabx 閱讀(317) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2009-12-01 16:02 xnabx 閱讀(191) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2009-12-01 11:05 xnabx 閱讀(327) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2009-11-10 09:05 xnabx 閱讀(766) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2009-03-18 14:06 xnabx 閱讀(153) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2008-10-29 16:34 xnabx 閱讀(115) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2008-07-30 15:18 xnabx 閱讀(244) | 評(píng)論 (0)編輯 收藏
               摘要:   閱讀全文
          posted @ 2008-07-23 11:20 xnabx 閱讀(389) | 評(píng)論 (0)編輯 收藏
          出處:http://www.aygfsteel.com/xmatthew/archive/2008/04/14/192450.html
          (轉(zhuǎn))設(shè)計(jì)一個(gè)Tomcat訪問日志分析工具
          常使用web服務(wù)器的朋友大都了解,一般的web server有兩部分日志:
              一是運(yùn)行中的日志,它主要記錄運(yùn)行的一些信息,尤其是一些異常錯(cuò)誤日志信息
              二是訪問日志信息,它記錄的訪問的時(shí)間,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提供的一個(gè)標(biāo)準(zhǔn)設(shè)置格式。其具體的表達(dá)式為 %h %l %u %t "%r" %s %b
              但本人建議采用以下具體的配置,因?yàn)闃?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)在我們回頭再來看一下下面這個(gè)配置 %h %l %u %t "%r" %s %b %T 生產(chǎn)的訪問日志數(shù)據(jù),我們可以做哪些事?
          先看一下,我們能得到的數(shù)據(jù)有:
              * %h 訪問的用戶IP地址
              * %l 訪問邏輯用戶名,通常返回'-'
              * %u 訪問驗(yàn)證用戶名,通常返回'-'
              * %t 訪問日時(shí)
              * %r 訪問的方式(post或者是get),訪問的資源和使用的http協(xié)議版本
              * %s 訪問返回的http狀態(tài)
              * %b 訪問資源返回的流量
              * %T 訪問所使用的時(shí)間
             
          有了這些數(shù)據(jù),我們可以根據(jù)時(shí)間段做以下的分析處理(圖片使用jfreechart工具動(dòng)態(tài)生成):
            * 獨(dú)立IP數(shù)統(tǒng)計(jì)
            * 訪問請(qǐng)求數(shù)統(tǒng)計(jì)
            * 訪問資料文件數(shù)統(tǒng)計(jì)
            * 訪問流量統(tǒng)計(jì)
            * 訪問處理響應(yīng)時(shí)間統(tǒng)計(jì)
            * 統(tǒng)計(jì)所有404錯(cuò)誤頁(yè)面
            * 統(tǒng)計(jì)所有500錯(cuò)誤的頁(yè)面
            * 統(tǒng)計(jì)訪問最頻繁頁(yè)面
            * 統(tǒng)計(jì)訪問處理時(shí)間最久頁(yè)面
            * 統(tǒng)計(jì)并發(fā)訪問頻率最高的頁(yè)面



























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

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

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

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

          2. 檢查Eclipse所使用的heap的大小。 在C:\eclipse目錄下有一個(gè)配置文件eclipse.ini,其中配置了Eclipse啟動(dòng)的默認(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. 其他的啟動(dòng)參數(shù)。 如果你有一個(gè)雙核的CPU,也許可以嘗試這個(gè)參數(shù):

          -XX:+UseParallelGC

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

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

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

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

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

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

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

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

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

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

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

          Public synchronized void methodAAA()

          {

          //….

          }

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

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

          public void methodAAA()

          {

          synchronized (this)      // (1)

          {

                 //…..

          }

          }

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

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

                     public void method3(SomeObject so)

                        {

                               synchronized(so)

          {

                 //…..

          }

          }

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

          class Foo implements Runnable

          {

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

              Public void methodA()

          {

                 synchronized(lock) { //… }

          }

          //…..

          }

          注:零長(zhǎng)度的byte數(shù)組對(duì)象創(chuàng)建起來將比任何對(duì)象都經(jīng)濟(jì)――查看編譯后的字節(jié)碼:生成零長(zhǎng)度的byte[]對(duì)象只需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)用這個(gè)方法的對(duì)象所屬的類(Class,而不再是由這個(gè)Class產(chǎn)生的某個(gè)具體對(duì)象了)。

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

          可以推斷:如果一個(gè)類中定義了一個(gè)synchronizedstatic函數(shù)A,也定義了一個(gè)synchronized instance函數(shù)B,那么這個(gè)類的同一對(duì)象Obj在多線程中分別訪問AB兩個(gè)方法時(shí),不會(huì)構(gòu)成同步,因?yàn)樗鼈兊逆i都不一樣。A方法的鎖是Obj這個(gè)對(duì)象,而B的鎖是Obj所屬的那個(gè)Class

          小結(jié)如下:

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

           

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

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

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


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

          這幾個(gè)學(xué)習(xí)材料非常短小精悍,可清晰快捷的掌握以下幾個(gè)概念,方便更深入學(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 閱讀(180) | 評(píng)論 (0)編輯 收藏


          類-->對(duì)象-->實(shí)例

          人類是類
          某個(gè)人是對(duì)象
          你是實(shí)例
          實(shí)例本身也是對(duì)象。

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

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

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

          2.?編碼基本知識(shí)?

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

          2.1.?iso8859-1?

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

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

          2.2.?GB2312/GBK?

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

          2.3.?unicode?

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

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

          2.4.?UTF?

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

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

          3.?java對(duì)字符的處理?

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

          3.1.?getBytes(charset)?

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

          3.2.?new?String(charset)?

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

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

          3.3.?setCharacterEncoding()?

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

          對(duì)于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()。而且,該指定只對(duì)POST方法有效,對(duì)GET方法無效。分析原因,應(yīng)該是在執(zhí)行第一個(gè)getParameter()的時(shí)候,java將會(huì)按照編碼分析所有的提交內(nèi)容,而后續(xù)的getParameter()不再進(jìn)行分析,所以setCharacterEncoding()無效。而對(duì)于GET方法提交表單是,提交的內(nèi)容在URL中,一開始就已經(jīng)按照編碼分析所有的提交內(nèi)容,setCharacterEncoding()自然就無效。?

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

          3.4.?處理過程?

          下面分析兩個(gè)有代表性的例子,說明java對(duì)編碼有關(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)存中以u(píng)nicode編碼則為4e2d?6587。?

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

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

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

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

          3.4.2.?文件編譯?

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

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

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

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

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

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

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

          3.5.1.?jsp編譯?

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

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

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

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

          3.5.4.?form設(shè)置?

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

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

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

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

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

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

          4.2.?apache?

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

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

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

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

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

          4.4.?其它?

          為了支持中文文件名,linux在加載磁盤時(shí)應(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è)置所有請(qǐng)求,而不能針對(duì)具體頁(yè)面進(jìn)行設(shè)置,也不一定和browser使用的編碼相同,所以有時(shí)候并不是所期望的。?

          5.?URL地址?

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

          5.1.?URL編碼?

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

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

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

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

          5.2.?rewrite?

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

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

          5.3.?URLEncode.encode()?

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

          當(dāng)不指定編碼的時(shí)候,該方法使用系統(tǒng)默認(rèn)編碼,這會(huì)導(dǎo)致軟件運(yùn)行結(jié)果得不確定。比如對(duì)于"中文",當(dāng)系統(tǒng)默認(rèn)編碼為"gb2312"時(shí),結(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時(shí)的環(huán)境變量LC_ALL和LANG等決定的,曾經(jīng)出現(xiàn)過tomcat重啟后就出現(xiàn)亂碼的問題,最后才郁悶的發(fā)現(xiàn)是因?yàn)樾薷男薷牧诉@兩個(gè)環(huán)境變量。?

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

          5.4.?一個(gè)解決方案?

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

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

          比較幸運(yùn)的是UTF-8編碼相當(dāng)有規(guī)律,所以可以通過分析傳輸過來的鏈接內(nèi)容,來判斷是否是正確的UTF-8字符,如果是,則以UTF-8處理之,如果不是,則使用客戶默認(rèn)編碼(比如"GBK"),下面是一個(gè)判斷是否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)地,一個(gè)使用上述方法的例子如下:?

          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?沒有包括對(duì)用戶默認(rèn)編碼的識(shí)別,這可以根據(jù)請(qǐng)求信息的語言來判斷,但不一定正確,因?yàn)槲覀冇袝r(shí)候也會(huì)輸入一些韓文,或者其他文字。?

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

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

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

          6.?其它?

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

          6.1.?SecureCRT?

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

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

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

          6.2.?過濾器?

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

          6.3.?POST和GET?

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

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

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

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

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

          posted @ 2006-08-30 17:51 xnabx 閱讀(177) | 評(píng)論 (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 閱讀(166) | 評(píng)論 (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 閱讀(155) | 評(píng)論 (0)編輯 收藏
          Unicode解決方案
          Unicode:寬字節(jié)字符集(摘自windows核心編程)

          UnicodeAppleXerox公司于1988年建立的一個(gè)技術(shù)標(biāo)準(zhǔn)。1991年,成立了一個(gè)集團(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
          提供了一種簡(jiǎn)單而又一致的表示字符串的方法。Unicode字符串中的所有字符都是16位的(兩個(gè)字節(jié))。它沒有專門的字節(jié)來指明下一個(gè)字節(jié)是屬于同一個(gè)字符的組成部分,還是一個(gè)新字符。這意味著你只需要對(duì)指針進(jìn)行遞增或遞減,就可以遍歷字符串中的各個(gè)字符,不再需要調(diào)用CharNext之類的函數(shù)。由于Unicode用一個(gè)16位的值來表示每個(gè)字符,因此總共可以得到65000個(gè)字符,這樣,它就能夠?qū)κ澜绺鲊?guó)的書面文字中的所有字符進(jìn)行編碼,遠(yuǎn)遠(yuǎn)超過了單字節(jié)字符集的256個(gè)字符的數(shù)目。




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

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

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

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

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

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

          posted @ 2006-03-27 17:49 xnabx 閱讀(154) | 評(píng)論 (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 閱讀(123) | 評(píng)論 (0)編輯 收藏
          pop-ent.21cn.com
          @shareinfo.com.cn
          posted @ 2006-03-27 16:51 xnabx 閱讀(146) | 評(píng)論 (0)編輯 收藏

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

          級(jí)聯(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是個(gè)接口,它的close實(shí)現(xiàn)可能是多種多樣的。在普通情況下,你用 DriverManager.getConnection()得到一個(gè)Connection實(shí)例,調(diào)用它的close方法會(huì)關(guān)閉Statement和 ResultSet。但是在很多時(shí)候,你需要使用數(shù)據(jù)庫(kù)連接池,在連接池中的得到的Connection上調(diào)用close方法的時(shí)候,Connection可能并沒有被釋放,而是回到了連接池中。它以后可能被其它代碼取出來用。如果沒有釋放Statement和ResultSet,那么在Connection上沒有關(guān)閉的Statement和ResultSet可能會(huì)越來越多,那么……
          相反,我看到過這樣的說法,有人把Connection關(guān)閉了,卻繼續(xù)使用ResultSet,認(rèn)為這樣是可以的,引發(fā)了激烈的討論,到底是怎么回事就不用我多說了吧。

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

          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) {
          ??? ///錯(cuò)誤處理
          }
          finally{
          ??? try {
          ??????? if(ps!=null)
          ??????????? ps.close();
          ??? }
          ??? catch (SQLException ex) {
          ??????? ///錯(cuò)誤處理
          ??? }
          ??? try{
          ??????? if(con!=null)
          ??????????? con.close();
          ??? }
          ??? catch (SQLException ex) {
          ??????? ///錯(cuò)誤處理
          ??? }
          }

          ?

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

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

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

          posted @ 2006-03-23 22:07 xnabx 閱讀(351) | 評(píng)論 (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 閱讀(156) | 評(píng)論 (0)編輯 收藏

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

          處理:
          //javascript

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

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


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

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

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

          問題:

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

          ArrayList a=new ArrayList();

          a.add(...);

          Iterator i=a.iterator();

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

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

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

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


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

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

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

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

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

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

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

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

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

          posted @ 2006-03-22 15:57 xnabx 閱讀(172) | 評(píng)論 (0)編輯 收藏
          1. 有一個(gè)ArrayList,里面包含N個(gè)Integer,其中的Integer都是由1至N+1的數(shù)字構(gòu)成,并且不重復(fù),但是有一個(gè)1至N+1的數(shù)字對(duì)應(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. 有一個(gè)二叉樹類如下。然后寫出遍歷二叉樹的方法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
          求一個(gè)方法,輸出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對(duì)象有哪些方法?
          ? 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有良好的生存期定義,包括加載,實(shí)例化,初始化,處理請(qǐng)求,服務(wù)結(jié)束。由javax.servlet.Servlet接口以下方法表達(dá)
          ? init(),service(),destroy()。

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

          extends一個(gè)類。

          11.實(shí)現(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差點(diǎn)。
          ? 當(dāng)增長(zhǎng)時(shí),Vector默認(rèn)增長(zhǎng)原來的一倍,ArrayList默認(rèn)增長(zhǎng)原來的一半。

          13.java實(shí)現(xiàn)序列化的方法是實(shí)現(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 = 星際) ( 一級(jí)(初級(jí))) 信譽(yù):100 2006-03-22 09:51:00 得分:0
          ?
          Top
          treeroot(旗魯特) ( 兩星(中級(jí))) 信譽(yù):106 2006-03-22 10:23:00 得分:0
          ?
          Top
          huyc_fly() ( 二級(jí)(初級(jí))) 信譽(yù):100 2006-03-22 11:09:00 得分:0
          ?
          Top
          larger102(駱駝) ( 三級(jí)(初級(jí))) 信譽(yù):100 2006-03-22 11:34:00 得分:0
          ?
          Top
          huyc_fly() ( 二級(jí)(初級(jí))) 信譽(yù):100 2006-03-22 11:55:00 得分:0
          ?
          Top
          echomyf(ECHO) ( 二級(jí)(初級(jí))) 信譽(yù):100 2006-03-22 12:42:00 得分:0
          ?
          Top
          diy8187(雞狗豬驢) ( 四級(jí)(中級(jí))) 信譽(yù):105 2006-03-22 13:00:00 得分:0
          ?
          Top
          hyper784533() ( 一級(jí)(初級(jí))) 信譽(yù):100 2006-03-22 13:05:00 得分:0
          ?
          posted @ 2006-03-22 15:53 xnabx 閱讀(223) | 評(píng)論 (0)編輯 收藏
          ? 問題一:
          ? 有int型數(shù)字如下,123,1234,12345,123456,1234567,12345678,123456789
          ? 求一個(gè)方法,輸出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 閱讀(907) | 評(píng)論 (2)編輯 收藏

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

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

          處理:

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

          posted @ 2006-03-22 14:19 xnabx 閱讀(214) | 評(píng)論 (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 閱讀(161) | 評(píng)論 (0)編輯 收藏

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

          處理:

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

          所以解決的方法就是?
          ???? 為session設(shè)置一個(gè)存活期: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 閱讀(158) | 評(píng)論 (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 %>">

          // *****************************頁(yè)面部分*********************************//

          </oscache:cache>

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

          這樣可以實(shí)現(xiàn)多態(tài),如果B和C都實(shí)現(xiàn)了接口A,那么我可以聲明一個(gè)A的對(duì)象變量,而實(shí)際的實(shí)例可能是B也可能是C
          多態(tài)----對(duì)同一個(gè)方法的調(diào)用,不同的實(shí)現(xiàn)類,有不同的響應(yīng)結(jié)果
          posted @ 2006-03-21 09:26 xnabx 閱讀(127) | 評(píng)論 (0)編輯 收藏
          new String(str.getBytes("gbk"),"utf-8")
          java中的字符串都是用unicode編碼來表示的,GBK編碼的漢字應(yīng)該是從程序外面獲得的(如數(shù)據(jù)庫(kù)中,或文本文件中), 例如從本地文本文件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 閱讀(1302) | 評(píng)論 (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里的一個(gè)input里?

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

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

          問題:
          A.JSP如下:
          ……

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

          ……


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

          }
          </script>
          ……

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

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

          posted @ 2006-03-20 13:43 xnabx 閱讀(999) | 評(píng)論 (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)在請(qǐng)教各位------怎么取到iframe中的某個(gè)參數(shù)的值?

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

          posted @ 2006-03-20 13:09 xnabx 閱讀(1251) | 評(píng)論 (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)容很長(zhǎng)時(shí),有些內(nèi)容看不到;如何做到該網(wǎng)頁(yè)隨iframe中嵌入的網(wǎng)頁(yè)內(nèi)容長(zhǎng)度自動(dòng)出現(xiàn)滾動(dòng)條,并且這滾動(dòng)條不是出現(xiàn)在iframe中

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

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

          主頁(yè)面要放置一個(gè)IFrame用于嵌套顯示子頁(yè)面的信息,但是子頁(yè)面的數(shù)據(jù)多少不一,導(dǎo)致子頁(yè)面可能會(huì)很長(zhǎng)或很短,要?jiǎng)討B(tài)控制IFrame的高低隨子頁(yè)面的長(zhǎng)短而變化。
          主頁(yè)面如下:
          <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>

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

          其中frmTest即為Main頁(yè)面的IFrame的ID。

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

          2.下面代碼的輸出是什么?一共在內(nèi)存中生成了幾個(gè)String對(duì)象?為什么?
          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處是否會(huì)有異常,如果沒有,輸出是什么?是否會(huì)運(yùn)行到2處,如果會(huì),輸出是什么?為什么會(huì)有這樣的結(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.請(qǐng)選出下面哪些描述是正確的。
          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.請(qǐng)寫出數(shù)據(jù)庫(kù)查詢操作的偽代碼,程序不需要通過編譯,只要思路正確,關(guān)鍵步驟不丟失就可以了。注意異常的捕獲,IO流的關(guān)閉。可能用到的類或接口有(Connection,DriverManager, Statement, PreparedStatement, ResultSet, SQLException)。

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

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

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

          5.1.2·實(shí)例

          考慮一下HelloWorld.java程序版本的簡(jiǎn)單擴(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)異常被拋出時(shí),在其循環(huán)被執(zhí)行四次之后,程序終止,并帶有
          錯(cuò)誤信息,就象前面所示的程序那樣。
          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),
          因此,錯(cuò)誤情況不會(huì)介入到程序的正常流程中。特殊情況發(fā)生時(shí),在與正常
          執(zhí)行的代碼分離的代碼塊中被處理。這就產(chǎn)生了更易識(shí)別和管理的代碼。

          5.2·異常處理

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

          ·try和catch語句

          要處理特殊的異常,將能夠拋出異常的代碼放入try塊中,然后創(chuàng)建相應(yīng)的
          catch塊的列表,每個(gè)可以被拋出異常都有一個(gè)。如果生成的異常與catch
          中提到的相匹配,那么catch條件的塊語句就被執(zhí)行。在try塊之后,可能
          有許多catch塊,每一個(gè)都處理不同的異常。
          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ī)制

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

          5.2.2·finally語句

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

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

          5.2.3·重訪前例

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

          5.4·共同異常

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

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

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

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

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

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

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

          5.6.1·介紹

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

          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·實(shí)例

          考慮一個(gè)客戶服務(wù)器程序。在客戶代碼中,要與服務(wù)器連接,并希望
          服務(wù)器在5秒鐘內(nèi)響應(yīng)。如果服務(wù)器沒有響應(yīng),那么,代碼就如下所述
          拋出一個(gè)異常(如一個(gè)用戶定義的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塊可以如前例所述那樣被嵌套。

          也可能部分地處理一個(gè)異常然后也將它拋出。如:
          try {
          .....
          .....
          } catch (ServerTimedOutException e) {
          System.out.println("Error caught ");
          throw e;
          }
          posted @ 2006-03-19 22:56 xnabx 閱讀(242) | 評(píng)論 (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 閱讀(317) | 評(píng)論 (0)編輯 收藏

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

          使用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還要具有報(bào)警的功能。我們?cè)撊绾卧O(shè)計(jì)針對(duì)該例子的類結(jié)構(gòu)呢(在本例中,主要是為了展示abstract class和interface反映在設(shè)計(jì)理念上的區(qū)別,其他方面無關(guān)的問題都做了簡(jiǎn)化或者忽略)下面將羅列出可能的解決方案,并從設(shè)計(jì)理念層面對(duì)這些不同的方案進(jìn)行分析。
          解決方案一:
          簡(jiǎn)單的在Door的定義中增加一個(gè)alarm方法,如下:

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


          或者

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


          那么具有報(bào)警功能的AlarmDoor的定義方式如下:

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


          或者

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


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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            三、Java中的I/O操作

            Java中以字節(jié)流(InputStream和OutputStream)、節(jié)符流(Reader和Writer)來分別讀寫二進(jìn)制數(shù)據(jù)和字符數(shù)據(jù),使用非常簡(jiǎn)單有效。Java類庫(kù)中的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è)計(jì),下面的幾行代碼將產(chǎn)生一個(gè)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)閉按鈕時(shí)能關(guān)閉Frame窗體,需要讓這個(gè)窗體響應(yīng)一個(gè)WindowEvent事件,具體的做法就是給這個(gè)窗體添加一個(gè)事件監(jiān)聽器對(duì)象,這個(gè)事件監(jiān)聽器就是WindowListener接口的實(shí)現(xiàn)。在上面的代碼中插入如下代碼就可以關(guān)閉窗體:

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

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

          五、Java中線程及同步控制

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

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

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

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

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

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

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

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

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

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

          Java SDK Micro Edition (J2ME)

          用于開發(fā)掌上電腦、手機(jī)等移動(dòng)通信設(shè)備上使用的應(yīng)用程序。并不是所有的移動(dò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ā)一般臺(tái)式機(jī)應(yīng)用程序。我們平時(shí)所說的JDK就指J2SE,而我們學(xué)Java就是從學(xué)習(xí)J2SE開始的。

          Java SDK Enterprise Edition (J2EE)

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

          (二)Java小程序 (Applet)

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

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

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

          將這個(gè)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è)計(jì)同后臺(tái)開發(fā)人員的工作可以有效分離。可以想像讓開發(fā)人員用Servlet寫一個(gè)花捎的Web頁(yè)面有多困難,所以JSP+Servlet混合Web應(yīng)用是比較理想的選擇。

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

          (五)Java Beans

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

          (六)Enterprise Java Beans (EJB)

          Java Bean實(shí)際上相當(dāng)于微軟COM模型中的本地進(jìn)程內(nèi)COM組件,它是不能被跨進(jìn)程訪問的。Enterprise Java Bean 相當(dāng)于DCOM,即分布式組件。它是基于Java的遠(yuǎn)程方法調(diào)用(RMI)技術(shù)的,所以EJB可以被遠(yuǎn)程訪問(跨進(jìn)程、跨計(jì)算機(jī))。但EJB必須被布署在諸如Webspere、WebLogic這樣的容器中,EJB客戶從不直接訪問真正的EJB組件,而是通過其容器訪問。EJB容器是EJB組件的代理,EJB組件由容器所創(chuàng)建和管理。客戶通過容器來訪問真正的EJB組件。

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

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

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



          數(shù)值類型:

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



          引用類型:

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



          類和對(duì)象:

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

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

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



          IO流:

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



          容器:

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



          AWT和SWING:

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

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

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

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

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


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

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


          3.F 鍵的用法

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


          4. Shift 鍵的用法

          添加多個(gè)相同組件: 按shift鍵在選項(xiàng)上選取組件,把組件添加到窗口即可
          調(diào)整組件間間隔和對(duì)齊: 假設(shè)有組件JPanel 1/2/3;(要達(dá)到3個(gè)組件寬度相同,組件間隔相等,并且都是依據(jù)JPanel1左對(duì)齊),按shift鍵,用鼠標(biāo)選中需要調(diào)整的組件,(第一個(gè)選中的組件是其他的基準(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 閱讀(177) | 評(píng)論 (0)編輯 收藏
          1.得到當(dāng)前程序文件的絕對(duì)路徑:this.getClass().getResource(this.getClass().getName()+".java").getPath()
          posted @ 2006-03-17 23:59 xnabx 閱讀(204) | 評(píng)論 (0)編輯 收藏

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

          至強(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)化方面的資料。硬件方面要升級(jí)哪些? 以達(dá)到支持大約在線用戶為最高2000人。

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

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

          ?? 當(dāng)在提交頁(yè)面里面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 因?yàn)?/span> HttpServletResponse.sendRedirect(…) 中解釋 URL 采用 ”/” 開頭相對(duì)于 servlet 容器根目錄。

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

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

          繁重

          posted @ 2006-03-14 15:37 xnabx 閱讀(170) | 評(píng)論 (0)編輯 收藏
          主站蜘蛛池模板: 密山市| 巧家县| 临沧市| 茂名市| 顺平县| 安国市| 岳阳市| 托克逊县| 卫辉市| 佛山市| 阿鲁科尔沁旗| 菏泽市| 南召县| 庆元县| 稷山县| 康乐县| 阳朔县| 大埔县| 泰宁县| 静海县| 麟游县| 桐柏县| 新巴尔虎左旗| 广南县| 信阳市| 抚远县| 三亚市| 苏尼特左旗| 班戈县| 社旗县| 高邑县| 长宁区| 烟台市| 澄江县| 天津市| 育儿| 兰西县| 甘南县| 灵璧县| 泗洪县| 遂川县|