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

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

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

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

    首先是配置tomcat訪問日志數據,默認情況下訪問日志沒有打開,配置的方式如下:
        編輯 ${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是產生的目錄 tomcat安裝${catalina}作為當前目錄
        pattern表示日志生產的格式,common是tomcat提供的一個標準設置格式。其具體的表達式為 %h %l %u %t "%r" %s %b
        但本人建議采用以下具體的配置,因為標準配置有一些重要的日志數據無法生。
            %h %l %u %t "%r" %s %b %T 
    具體的日志產生樣式說明如下(從官方文檔中摘錄):
        * %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


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



























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

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

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

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

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

    -vmargs
    -Xms40M
    -Xmx256M

    所以你可以把默認值改為:

    -vmargs
    -Xms256M
    -Xmx512M

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

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

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

    -XX:+UseParallelGC

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

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

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

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

    在進一步闡述之前,我們需要明確幾點:

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

    B.每個對象只有一個鎖(lock)與之相關聯。

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

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

    假設P1、P2是同一個類的不同對象,這個類中定義了以下幾種情況的同步塊或同步方法,P1、P2就都可以調用它們。

    1. synchronized當作函數修飾符時,示例代碼如下:

    Public synchronized void methodAAA()

    {

    //….

    }

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

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

    public void methodAAA()

    {

    synchronized (this)      // (1)

    {

           //…..

    }

    }

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

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

               public void method3(SomeObject so)

                  {

                         synchronized(so)

    {

           //…..

    }

    }

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

    class Foo implements Runnable

    {

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

        Public void methodA()

    {

           synchronized(lock) { //… }

    }

    //…..

    }

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

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

          Class Foo

    {

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

    {

    //….

    }

    public void methodBBB()

    {

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

    }

           }

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

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

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

    小結如下:

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

     

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

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

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


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

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

    XML tutorial:

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

     

    SOAP tutorial:

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

     

    WSDL tutorial:

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

     

    WEB Service tutorial:

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

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


    類-->對象-->實例

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

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

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

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

    2.?編碼基本知識?

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

    2.1.?iso8859-1?

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

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

    2.2.?GB2312/GBK?

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

    2.3.?unicode?

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

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

    2.4.?UTF?

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

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

    3.?java對字符的處理?

    在java應用軟件中,會有多處涉及到字符集編碼,有些地方需要進行正確的設置,有些地方需要進行一定程度的處理。?

    3.1.?getBytes(charset)?

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

    3.2.?new?String(charset)?

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

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

    3.3.?setCharacterEncoding()?

    該函數用來設置http請求或者相應的編碼。?

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

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

    3.4.?處理過程?

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

    3.4.1.?表單輸入?

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

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

    l?從browser到web?server,可以在表單中指定提交內容時使用的字符集,否則會使用頁面指定的編碼。而如果在url中直接用?的方式輸入參數,則其編碼往往是操作系統本身的編碼,因為這時和頁面無關。上述仍舊以gbk編碼為例。?

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

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

    3.4.2.?文件編譯?

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

    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編譯的結果是不正確的。?

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

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

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

    l?Java編譯的時候會轉換成統一的unicode編碼處理,最后保存的時候再轉換為utf編碼。?

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

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

    3.5.?幾處設置?

    對于web應用程序,和編碼有關的設置或者函數如下。?

    3.5.1.?jsp編譯?

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

    3.5.2.?jsp輸出?

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

    3.5.3.?meta設置?

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

    如果同時采用了jsp輸出和meta設置兩種編碼指定方式,則jsp指定的優先。因為jsp指定的直接體現在response中。?

    需要注意的是,apache有一個設置可以給無編碼指定的網頁指定編碼,該指定等同于jsp的編碼指定方式,所以會覆蓋靜態網頁中的meta指定。所以有人建議關閉該設置。?

    3.5.4.?form設置?

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

    4.?系統軟件?

    下面討論幾個相關的系統軟件。?

    4.1.?mysql數據庫?

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

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

    4.2.?apache?

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

    另外,apache還有單獨的模塊來處理網頁響應頭,其中也可能對編碼進行設置。?

    4.3.?linux默認編碼?

    這里所說的linux默認編碼,是指運行時的環境變量。兩個重要的環境變量是LC_ALL和LANG,默認編碼會影響到java?URLEncode的行為,下面有描述。?

    建議都設置為"zh_CN.UTF-8"。?

    4.4.?其它?

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

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

    5.?URL地址?

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

    5.1.?URL編碼?

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

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

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

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

    5.2.?rewrite?

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

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

    5.3.?URLEncode.encode()?

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

    當不指定編碼的時候,該方法使用系統默認編碼,這會導致軟件運行結果得不確定。比如對于"中文",當系統默認編碼為"gb2312"時,結果是"%4e%2d%65%87",而默認編碼為"UTF-8",結果卻是"%e4%b8%ad%e6%96%87",后續程序將難以處理。另外,這兒說的系統默認編碼是由運行tomcat時的環境變量LC_ALL和LANG等決定的,曾經出現過tomcat重啟后就出現亂碼的問題,最后才郁悶的發現是因為修改修改了這兩個環境變量。?

    建議統一指定為"UTF-8"編碼,可能需要修改相應的程序。?

    5.4.?一個解決方案?

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

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

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

    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;?

    }?

    相應地,一個使用上述方法的例子如下:?

    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?沒有包括對用戶默認編碼的識別,這可以根據請求信息的語言來判斷,但不一定正確,因為我們有時候也會輸入一些韓文,或者其他文字。?

    l?可能會錯誤判斷UTF-8字符,一個例子是"學習"兩個字,其GBK編碼是"?\xd1\xa7\xcf\xb0",如果使用上述isValidUtf8方法判斷,將返回true??梢钥紤]使用更嚴格的判斷方法,不過估計效果不大。?

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

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

    6.?其它?

    下面描述一些和編碼有關的其他問題。?

    6.1.?SecureCRT?

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

    另外,mysql有自己的編碼設置,也應該保持和SecureCRT的顯示編碼一致。否則通過SecureCRT執行sql語句的時候,可能無法處理中文字符,查詢結果也會出現亂碼。?

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

    6.2.?過濾器?

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

    6.3.?POST和GET?

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

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

    6.4.?簡繁體編碼轉換?

    GBK同時包含簡體和繁體編碼,也就是說同一個字,由于編碼不同,在GBK編碼下屬于兩個字。有時候,為了正確取得完整的結果,應該將繁體和簡體進行統一??梢钥紤]將UTF、GBK中的所有繁體字,轉換為相應的簡體字,BIG5編碼的數據,也應該轉化成相應的簡體字。當然,仍舊以UTF編碼存儲。?

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

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

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

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

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

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

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

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

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

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

    插入排序:

    package org.rut.util.algorithm.support;

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

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

    }
    冒泡排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

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

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

    }

    選擇排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

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

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

    }

    Shell排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

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

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

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

    }

    快速排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

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

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

    }
    改進后的快速排序:

    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++];???????????
    ??????? }
    ??? }

    }

    改進后的歸并排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

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

    ??? private static final int THRESHOLD = 10;

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

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

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

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

    }
    堆排序:

    package org.rut.util.algorithm.support;

    import org.rut.util.algorithm.SortUtil;

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

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


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

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

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

    ??? }

    }

    ?

    SortUtil:

    package org.rut.util.algorithm;

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

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

    ??? public final static int BUBBLE = 2;

    ??? public final static int SELECTION = 3;

    ??? public final static int SHELL = 4;

    ??? public final static int QUICK = 5;

    ??? public final static int IMPROVED_QUICK = 6;

    ??? public final static int MERGE = 7;

    ??? public final static int IMPROVED_MERGE = 8;

    ??? public final static int HEAP = 9;

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

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

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

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

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

    UnicodeAppleXerox公司于1988年建立的一個技術標準。1991年,成立了一個集團機構負責Unicode的開發和推廣應用。該集團由AppleCompaqIBM、Microsoft、Oracle、Silicon ? Graphics, ? Inc.SybaseUnisysXerox等公司組成。該集團負責維護Unicode標準。
    Unicode
    提供了一種簡單而又一致的表示字符串的方法。Unicode字符串中的所有字符都是16位的(兩個字節)。它沒有專門的字節來指明下一個字節是屬于同一個字符的組成部分,還是一個新字符。這意味著你只需要對指針進行遞增或遞減,就可以遍歷字符串中的各個字符,不再需要調用CharNext之類的函數。由于Unicode用一個16位的值來表示每個字符,因此總共可以得到65000個字符,這樣,它就能夠對世界各國的書面文字中的所有字符進行編碼,遠遠超過了單字節字符集的256個字符的數目。




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

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

    明白Unicode和DBCS之間的區別很重要。Unicode使用(特別在C程序設計語言環境里)“寬字符集”?!癠nicode中的每個字符都是16位寬而不是8位寬。”在Unicode中,沒有單單使用8位數值的意義存在。相比之下,在雙字節字符集中我們仍然處理8位數值。有些字節自身定義字符,而某些字節則顯示需要和另一個字節共同定義一個字符。

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

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

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

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

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

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

    效果圖:

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

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

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

    在Connection上調用close方法會關閉Statement和ResultSet嗎?

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

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

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

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

    ?

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

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

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

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

    public class TranCharset {

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

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

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

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

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

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

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

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

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

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

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

    處理:
    //javascript

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

    注:用ascII碼控制。好像漢字都是負數


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

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

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

    問題:

    在ArrayList 應用中有這樣的代碼:

    ArrayList a=new ArrayList();

    a.add(...);

    Iterator i=a.iterator();

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

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

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

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


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

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

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

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

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

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

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

    無:默認的.當修飾符默認時,說明該類成員能被同一類中的其他成員,或同一包中的其他類訪問,不能被其他包的類訪問

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

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

    不存在ArrayList中,求該數。

    public static void main(String[] args){

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

    }


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

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

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

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

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

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

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

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

    6.RuntimeException,非RuntimeException的區別和例子。

    7.Singleton模式

    8.共享數據在web中的范圍
    ? page,request,seesion,application

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

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

    extends一個類。

    11.實現多線程有哪幾種方法。
    第一種,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的區別。
    ? Vector中的方法是synchronized的,性能上較ArrayList差點。
    ? 當增長時,Vector默認增長原來的一倍,ArrayList默認增長原來的一半。

    13.java實現序列化的方法是實現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的區別。RequestProcessor的作用。


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

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


    ?問題二、
    double類型如何正確的轉換為字符串類型

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

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

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

    處理:

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

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

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

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

    處理:

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

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

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

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


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

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

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

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

    </oscache:cache>

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

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

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

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

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

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

    問題:
    A.JSP如下:
    ……

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

    ……


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

    }
    </script>
    ……

    請問如何在A.jsp里調用該C方法?

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

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

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

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

    現在在Action里取到的學生所在地區的id總是空,我現在請教各位------怎么取到iframe中的某個參數的值?

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

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

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

    現在的問題是當frame2.htm顯示的內容很長時,有些內容看不到;如何做到該網頁隨iframe中嵌入的網頁內容長度自動出現滾動條,并且這滾動條不是出現在iframe中

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

    問題二、如何動態控制IFrame的長和寬

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

    7.仔細分析下面的程序,寫出程序的輸出結果。
    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.請寫出數據庫查詢操作的偽代碼,程序不需要通過編譯,只要思路正確,關鍵步驟不丟失就可以了。注意異常的捕獲,IO流的關閉。可能用到的類或接口有(Connection,DriverManager, Statement, PreparedStatement, ResultSet, SQLException)。

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

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

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

    5.1.2·實例

    考慮一下HelloWorld.java程序版本的簡單擴展,它通過信息來循環:
    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. }

    正常情況下,當異常被拋出時,在其循環被執行四次之后,程序終止,并帶有
    錯誤信息,就象前面所示的程序那樣。
    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)

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

    5.2·異常處理

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

    ·try和catch語句

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

    5.2.1·調用棧機制

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

    5.2.2·finally語句

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

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

    5.2.3·重訪前例

    下面的例子是第169頁main()方法的重寫。本程序以前的版本中產生的
    異常被捕獲,數組索引重新設定,使下述程序繼續運行。
    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()

    當循環被執行時,下述在屏幕上出現的信息將改變。

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

    5.4·共同異常

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

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

    5.5·處理或聲明規則

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

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

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

    5.6·創建自己的異常

    5.6.1·介紹

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

    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. }

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

    5.6.2·實例

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

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

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

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

    abstract class和interface是Java語言中對于抽象類定義進行支持的兩種機制,正是由于這兩種機制的存在,才賦予了Java強大的面向對象能力。
    接口:沒有提供任何具體實現,可以說是一個極度抽象的類,他允許你創建一個能夠被向上轉型為不止一種基類型的類,以此來實現多重繼承。
    抽象類:包含一種或多種抽象方法的類,且可以提供具體的實現。定義抽象類后,其他類可以對他進行擴充并且通過實現其中的抽象方法,使用抽象類具體話。
    Java中的接口和抽象類的區別:接口中沒有屬性,而且所有的方法都是抽象的,而抽象類可以有屬性,而且可以有抽象方法,也可以有實現的方法。但兩者都不能被實例話。
    使用的時候,一個類可以繼承多個接口,但只能繼承一個抽象類。
    一、理解抽象類
    abstract class和interface在Java語言中都是用來進行抽象類(本文中的抽象類并非從abstract class翻譯而來,它表示的是一個抽象體,而abstract class為Java語言中用于定義抽象類的一種方法,請讀者注意區分)定義的,那么什么是抽象類,使用抽象類能為我們帶來什么好處呢?
    在面向對象的概念中,我們知道所有的對象都是通過類來描繪的,但是反過來卻不是這樣。并不是所有的類都是用來描繪對象的,如果一個類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類就是抽象類。抽象類往往用來表征我們在對問題領域進行分析、設計中得出的抽象概念,是對一系列看上去不同,但是本質上相同的具體概念的抽象。
    比如:如果我們進行一個圖形編輯軟件的開發,就會發現問題領域存在著圓、三角形這樣一些具體概念,它們是不同的,但是它們又都屬于形狀這樣一個概念,形狀這個概念在問題領域是不存在的,它就是一個抽象概念。正是因為抽象的概念在問題領域沒有對應的具體概念,所以用以表征抽象概念的抽象類是不能夠實例化的。
    在面向對象領域,抽象類主要用來進行類型隱藏。我們可以構造出一個固定的一組行為的抽象描述,但是這組行為卻能夠有任意個可能的具體實現方式。這個抽象描述就是抽象類,而這一組任意個可能的具體實現則表現為所有可能的派生類。模塊可以操作一個抽象體。由于模塊依賴于一個固定的抽象體,因此它可以是不允許修改的;同時,通過從這個抽象體派生,也可擴展此模塊的行為功能。熟悉OCP的讀者一定知道,為了能夠實現面向對象設計的一個最核心的原則OCP(Open-Closed Principle),抽象類是其中的關鍵所在。
    二、從語法定義層面看abstract class和interface
    在語法層面,Java語言對于abstract class和interface給出了不同的定義方式,下面以定義一個名為Demo的抽象類為例來說明這種不同。使用abstract class的方式定義Demo抽象類的方式如下:

    abstract class Demo {
    abstract void method1();
    abstract void method2();


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

    interface Demo {
    void method1();
    void method2();

    }


    在abstract class方式中,Demo可以有自己的數據成員,也可以有非abstarct的成員方法,而在interface方式的實現中,Demo只能夠有靜態的不能被修改的數據成員(也就是必須是static final的,不過在interface中一般不定義數據成員),所有的成員方法都是abstract的。從某種意義上說,interface是一種特殊形式的abstract class。
    從編程的角度來看,abstract class和interface都可以用來實現"design by contract"的思想。但是在具體的使用上面還是有一些區別的。
    首先,abstract class在Java語言中表示的是一種繼承關系,一個類只能使用一次繼承關系。但是,一個類卻可以實現多個interface。也許,這是Java語言的設計者在考慮Java對于多重繼承的支持方面的一種折中考慮吧。
    其次,在abstract class的定義中,我們可以賦予方法的默認行為。但是在interface的定義中,方法卻不能擁有默認行為,為了繞過這個限制,必須使用委托,但是這會 增加一些復雜性,有時會造成很大的麻煩。
    在抽象類中不能定義默認行為還存在另一個比較嚴重的問題,那就是可能會造成維護上的麻煩。因為如果后來想修改類的界面(一般通過abstract class或者interface來表示)以適應新的情況(比如,添加新的方法或者給已用的方法中添加新的參數)時,就會非常的麻煩,可能要花費很多的時間(對于派生類很多的情況,尤為如此)。但是如果界面是通過abstract class來實現的,那么可能就只需要修改定義在abstract class中的默認行為就可以了。
    同樣,如果不能在抽象類中定義默認行為,就會導致同樣的方法實現出現在該抽象類的每一個派生類中,違反了"one rule,one place"原則,造成代碼重復,同樣不利于以后的維護。因此,在abstract class和interface間進行選擇時要非常的小心。
    三、從設計理念層面看abstract class和interface
    上面主要從語法定義和編程的角度論述了abstract class和interface的區別,這些層面的區別是比較低層次的、非本質的。本文將從另一個層面:abstract class和interface所反映出的設計理念,來分析一下二者的區別。作者認為,從這個層面進行分析才能理解二者概念的本質所在。
    前面已經提到過,abstarct class在Java語言中體現了一種繼承關系,要想使得繼承關系合理,父類和派生類之間必須存在"is a"關系,即父類和派生類在概念本質上應該是相同的。對于interface 來說則不然,并不要求interface的實現者和interface定義在概念本質上是一致的,僅僅是實現了interface定義的契約而已。為了使論述便于理解,下面將通過一個簡單的實例進行說明。
    考慮這樣一個例子,假設在我們的問題領域中有一個關于Door的抽象概念,該Door具有執行兩個動作open和close,此時我們可以通過abstract class或者interface來定義一個表示該抽象概念的類型,定義方式分別如下所示:

    使用abstract class方式定義Door:

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

    使用interface方式定義Door:

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


    其他具體的Door類型可以extends使用abstract class方式定義的Door或者implements使用interface方式定義的Door。看起來好像使用abstract class和interface沒有大的區別。
    如果現在要求Door還要具有報警的功能。我們該如何設計針對該例子的類結構呢(在本例中,主要是為了展示abstract class和interface反映在設計理念上的區別,其他方面無關的問題都做了簡化或者忽略)下面將羅列出可能的解決方案,并從設計理念層面對這些不同的方案進行分析。
    解決方案一:
    簡單的在Door的定義中增加一個alarm方法,如下:

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


    或者

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


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

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


    或者

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


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

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


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

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

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

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

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

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

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

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

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

    以下是Java標準技術的一些要點:

    一、Java的跨平臺性,即一次編譯到處運行

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

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

      二、面象對象技術

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

      三、Java中的I/O操作

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

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

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

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

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

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

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

    這里用到一個無名內部類,無名內部類是Java中內部類的一種靈活運用方式。

    五、Java中線程及同步控制

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

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

      用同步控制關鍵字synchronized來保護線程敏感數據,synchronized塊中的內容可以保證同一時刻只能被一個線程訪問,所以其中的數據是線程安全的。

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

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

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

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

      1、在Java中聲明native()方法,然后編譯;
      2、用javah產生一個.h文件;
     ?。场懸粋€.cpp文件實現native導出方法,其中需要包含第二步產生的.h文件(注意其中又包含了JDK帶的jni.h文件);
     ?。础⒌谌降?cpp文件編譯成動態鏈接庫文件;
     ?。?、在Java中用System.loadLibrary()方法加載第四步產生的動態鏈接庫文件,這個native()方法就可以在Java中被訪問了。

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

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

    Java SDK Micro Edition (J2ME)

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

    Java SDK Standard Edition(J2SE)

    主要用于開發一般臺式機應用程序。我們平時所說的JDK就指J2SE,而我們學Java就是從學習J2SE開始的。

    Java SDK Enterprise Edition (J2EE)

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

    (二)Java小程序 (Applet)

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

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

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

    public class Myservlet extends HttpServlet{

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

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

    (四)Java Server Page (JSP)

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

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

    (五)Java Beans

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

    (六)Enterprise Java Beans (EJB)

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

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

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

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



    數值類型:

      雖然是面向對象的語言,但是在使用上數值類型還是必不可少的,如果在C的學習中已經掌握了C的數值計算和轉換規則,那我想這里應該沒有什么問題,只有兩點需要注意:1、14.0這樣的浮點常量被認為是double型,只有加上f后綴才是float型的;2、整數常量說起來被認為是int型,但是在編譯時,可以認為編譯器將其看作能表示該數的最小數值,因此byte b = 100;不會報錯。



    引用類型:

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



    類和對象:

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

    函數調用的參數傳遞:

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



    IO流:

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



    容器:

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



    AWT和SWING:

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

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

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

    1.工作區: (顯隱)

    項目面板:ctrl + Alt + p (Project)
    設計面板: ctrl + Alt + c (content)
    結構面板: ctrl + Alt + s (Structure)
    信息面板: ctrl + Alt + M (Message)
    狀態面板: ctrl + Alt + Z


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

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


    3.F 鍵的用法

    F1: 幫助快捷
    F4: 運行多行
    F5: 加入斷點
    F7: 當遇到方法時會運行方法內的代碼
    F8: 逐步運行代碼
    F12: 代碼面板和設計面板切換


    4. Shift 鍵的用法

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


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

    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(開發人員可以用主菜單上的Tools/Editor/Templates命令來查看代碼摸板的名字)
    2、把光標定位于想要輸入代碼的位置,然后按ctrl + J

    posted @ 2006-03-18 00:23 xnabx 閱讀(173) | 評論 (0)編輯 收藏
    主站蜘蛛池模板: 亚洲欧洲国产日韩精品| 日日噜噜噜噜夜夜爽亚洲精品| 久久精品免费一区二区喷潮| 影音先锋在线免费观看| 国产午夜影视大全免费观看| 亚洲视频人成在线播放| 亚洲av无码专区国产乱码在线观看| 亚洲色欲或者高潮影院| 亚洲成a人片在线观看精品| 国产精品亚洲综合天堂夜夜| 国产成人高清精品免费观看| 99在线观看视频免费| 免费无码AV电影在线观看| 免费在线观看一级毛片| 亚洲VA中文字幕无码一二三区| 亚洲免费中文字幕| 国产成人亚洲午夜电影| 免费精品99久久国产综合精品| 国产一卡二卡3卡四卡免费| 亚洲AV中文无码乱人伦在线视色| 亚洲αv久久久噜噜噜噜噜| 亚洲一区二区三区在线观看网站| www免费插插视频| 国产精品视频免费| 亚洲视频一区二区| 亚洲AV综合色区无码二区爱AV| 青青青视频免费观看| 永久看日本大片免费35分钟| 免费a级毛片永久免费| 亚洲国产精品久久久久网站| 亚洲AV成人无码网天堂| 久草福利资源网站免费| 免费毛片在线视频| 久久精品亚洲视频| 精品亚洲视频在线| 91免费在线播放| 中文字幕亚洲电影| 亚洲中文无码永久免| 曰批全过程免费视频在线观看无码| 四虎成人免费影院网址| 久久久久亚洲Av片无码v|