亚洲综合成人网,国产综合第一页,久久伊伊香蕉http://www.aygfsteel.com/cyantide/category/36404.htmlzh-cnFri, 19 Mar 2010 18:21:40 GMTFri, 19 Mar 2010 18:21:40 GMT60java vm xms xmx查看http://www.aygfsteel.com/cyantide/archive/2010/03/19/315982.htmlcyantidecyantideFri, 19 Mar 2010 15:24:00 GMThttp://www.aygfsteel.com/cyantide/archive/2010/03/19/315982.htmlhttp://www.aygfsteel.com/cyantide/comments/315982.htmlhttp://www.aygfsteel.com/cyantide/archive/2010/03/19/315982.html#Feedback0http://www.aygfsteel.com/cyantide/comments/commentRss/315982.htmlhttp://www.aygfsteel.com/cyantide/services/trackbacks/315982.html <html>
     <%= "TotalMemory :::: " + (Runtime.getRuntime().totalMemory()/(1024*1024) + "M") %> 
   <%="Max Memory :::: " + (Runtime.getRuntime().maxMemory()/(1024*1024) + "M")%> 
   <%="Free Memory :::: " + (Runtime.getRuntime().freeMemory()/(1024*1024) + "M")%>   
</html>



cmd
   java -Xmx1024M -Xms1024M -version

cyantide 2010-03-19 23:24 發(fā)表評論
]]>
java面試題http://www.aygfsteel.com/cyantide/archive/2009/01/13/251063.htmlcyantidecyantideTue, 13 Jan 2009 01:41:00 GMThttp://www.aygfsteel.com/cyantide/archive/2009/01/13/251063.htmlhttp://www.aygfsteel.com/cyantide/comments/251063.htmlhttp://www.aygfsteel.com/cyantide/archive/2009/01/13/251063.html#Feedback1http://www.aygfsteel.com/cyantide/comments/commentRss/251063.htmlhttp://www.aygfsteel.com/cyantide/services/trackbacks/251063.html第一,談?wù)刦inal, finally, finalize的區(qū)別。

 

 final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。finally是異常處理語句結(jié)構(gòu)的一部分,表示總是執(zhí)行。finalize是 Object類的一個方法,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關(guān)閉文件等。

 

第二,Anonymous Inner Class (匿名內(nèi)部類) 是否可以extends(繼承)其它類,是否可以implements(實現(xiàn))interface(接口)?

 

 可以繼承其他類或完成其他接口,在swing編程中常用此方式。 

 

第三,Static Nested Class 和 Inner Class的不同,說得越多越好(面試題有的很籠統(tǒng))。

 

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

 

第四,&和&&的區(qū)別。

 

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

 

第五,HashMap和Hashtable的區(qū)別。

 

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

 

第六,Collection 和 Collections的區(qū)別。

  

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

 

第七,什么時候用assert。

 

 1.4新增關(guān)鍵字(語法),用于測試boolean表達(dá)式狀態(tài),可用于調(diào)試程序。使用方法 assert ,表示如果表達(dá)式為真(true),則下面的語句執(zhí)行,否則拋出AssertionError。另外的使用方式assert < boolean表達(dá)式>:,表示如果表達(dá)式為真,后面的表達(dá)式忽略,否則后面表達(dá)式的值用于AssertionError的構(gòu)建參數(shù)。注意編譯時要增加-source 1.4 參數(shù),否則報錯。]運(yùn)行時要增加 –ea參數(shù),否則assert行被忽略  

 

第八,GC是什么? 為什么要有GC?

  

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

 

第九,String s = new String("xyz");創(chuàng)建了幾個String Object?

 

 兩個  

 

第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

 

 Math.round(11.5)==12Math.round(-11.5)==-11round方法返回與參數(shù)最接近的長整數(shù),參數(shù)加1/2后求其floor.  

 

第十一,short s1 = 1; s1 = s1 + 1;有什么錯? short s1 = 1; s1 += 1;有什么錯?

 

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

 

第十二,sleep() 和 wait() 有什么區(qū)別?

 

 sleep是線程類(Thread)的方法,導(dǎo)致此線程暫停執(zhí)行指定時間,給執(zhí)行機(jī)會給其他線程,但是監(jiān)控狀態(tài)依然保持,到時后會自動恢復(fù)。調(diào)用 sleep不會釋放對象鎖。wait是Object類的方法,對此對象調(diào)用wait方法導(dǎo)致本線程放棄對象鎖,進(jìn)入等待此對象的等待鎖定池,只有針對此對象發(fā)出notify方法(或notifyAll)后本線程才進(jìn)入對象鎖定池準(zhǔn)備獲得對象鎖進(jìn)入運(yùn)行狀態(tài)。  

 

第十三,Java有沒有g(shù)oto?

 

 沒有  很十三的問題,如果哪個面試的問到這個問題,我勸你還是別進(jìn)這家公司。

 

第十四,數(shù)組有沒有l(wèi)ength()這個方法? String有沒有l(wèi)ength()這個方法?

 

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

 String有有l(wèi)ength()這個方法。

 

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

 

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

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

 

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

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

 

第十七,給我一個你最常見到的runtime exception。

 

參考如下:

ArithmeticException,

ArrayStoreException,

BufferOverflowException,

BufferUnderflowException,

CannotRedoException,

CannotUndoException,

ClassCastException,

CMMException,

ConcurrentModificationException,

DOMException,

EmptyStackException,

IllegalArgumentException,

IllegalMonitorStateException,

IllegalPathStateException,

IllegalStateException,

ImagingOpException,

IndexOutOfBoundsException,

MissingResourceException,

NegativeArraySizeException,

NoSuchElementException,

NullPointerException,

ProfileDataException,

ProviderException,

RasterFormatException,

SecurityException,

SystemException,

UndeclaredThrowableException,

UnmodifiableSetException,

UnsupportedOperationException

 

第十八,error和exception有什么區(qū)別?

 

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

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

 

第十九,List, Set, Map是否繼承自Collection接口?

 

List,Set是

Map不是

 

第二十,abstract class和interface有什么區(qū)別?

 

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

 

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

 

第二十一,abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?

 

都不能

 

第二十二,接口是否可繼承接口? 抽象類是否可實現(xiàn)(implements)接口? 抽象類是否可繼承實體類(concrete class)?

 

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

 

第二十三,啟動一個線程是用run()還是start()?

 

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

 

第二十四,構(gòu)造器Constructor是否可被override?

 

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

 

第二十五,是否可以繼承String類?

 

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

 

第二十六,當(dāng)一個線程進(jìn)入一個對象的一個synchronized方法后,其它線程是否可進(jìn)入此對象的其它方法?

 

 不能,一個對象的一個synchronized方法只能由一個線程訪問。

第二十七,try {}里有一個return語句,那么緊跟在這個try后的finally {}里的code會不會被執(zhí)行,什么時候被執(zhí)行,在return前還是后?

 

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

 

第二十八,編程題: 用最有效率的方法算出2乘以8等於幾?

 

有C背景的程序員特別喜歡問這種問題。

2 < < 3

 

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

 

不對,有相同的hash code。

 

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

 

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

 

第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

 

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

 

第三十二,編程題: 寫一個Singleton出來。

 

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

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

 

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

 

public class Singleton {

  private Singleton(){}

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

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

  private static Singleton instance = new Singleton();

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

  public static Singleton getInstance() {

    return instance;   

   }

 

 

第二種形式:

 

public class Singleton {

  private static Singleton instance = null;

  public static synchronized Singleton getInstance() {

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

  //使用時生成實例,提高了效率!

  if (instance==null)

    instance=new Singleton();

return instance;   }

 

 

其他形式:

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

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

 

 


其中也存在一些問題,下面補(bǔ)充一下.希望大家繼續(xù)補(bǔ)充

 

 

 

 

1.最好介紹一下final修飾變量的情形(分開說明基本類型變量和引用類型變量)。

2.不知道如何描述比較好,匿名內(nèi)部類本身是一個實現(xiàn)了特定接口或繼承了其他類的類。

3.非靜態(tài)類不能有static的方法。參考一下java collections framework的代碼,還能說出很多東西來。

4.&既是位運(yùn)算符,也是邏輯操作符。

&和&&都是邏輯運(yùn)算符,它們的區(qū)別是,&&進(jìn)行短路計算。

6.可以補(bǔ)充一下,參考文檔。

11.說一下具體的原因可能更好。

13.java有g(shù)oto這個keyword,不過還沒有使用。

15.overload和多態(tài)沒有任何關(guān)系。多態(tài)是面向?qū)ο蟮幕咎卣鳎呛屠^承、overriding相關(guān)的。原來以為把overload當(dāng)作多態(tài)的一種是從C++來的,后來翻了基本c++的經(jīng)典的書,也強(qiáng)調(diào)多態(tài)只是和繼承,虛函數(shù),overriding相關(guān),所以不知道這個錯誤思想從哪來的了.

16.public interface Set <E>extends Collection <E>一個不包含重復(fù)元素的 collection。更確切地講,set 不包含滿足 e1.equals(e2) 的元素對 e1 和 e2,并且最多包含一個 null 元素。正如其名稱所暗示的,此接口模仿了數(shù)學(xué)上的 set 抽象。

看文檔就是了.

22."抽象類是否可繼承實體類,但前提是實體類必須有明確的構(gòu)造函數(shù)。"什么意思?誰規(guī)定的?

27.這個比較復(fù)雜,例如

 

public class Main {

 

    public static void main(String[] args) {

        System.out.println(test());

    }

 

    public static boolean test() {

        boolean b = false;

        try {

 

            return b = 4 > 3;

        } finally {

            System.out.println(b);

          //return false;

        }

    } 

}

這個例子中可以看出,return后面的表達(dá)式已經(jīng)計算了,感覺return語句這里被掛起了,如果finally中沒有return,這個return就返回.

如果finally也有return,那么就是finally中的return返回了.

29.碰上不守規(guī)矩的程序員誰也沒辦法.

 

31.還有枚舉呢

32.注釋有問題.



cyantide 2009-01-13 09:41 發(fā)表評論
]]>
Java GUI 的默認(rèn)顯示格式設(shè)置http://www.aygfsteel.com/cyantide/archive/2008/08/28/225350.htmlcyantidecyantideThu, 28 Aug 2008 09:14:00 GMThttp://www.aygfsteel.com/cyantide/archive/2008/08/28/225350.htmlhttp://www.aygfsteel.com/cyantide/comments/225350.htmlhttp://www.aygfsteel.com/cyantide/archive/2008/08/28/225350.html#Feedback0http://www.aygfsteel.com/cyantide/comments/commentRss/225350.htmlhttp://www.aygfsteel.com/cyantide/services/trackbacks/225350.htmlJava GUI 的默認(rèn)顯示格式設(shè)置

try{
     UIManager.setLookAndFeel(
"com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
}
catch(Exception e){
     e.printStackTrace();
}


cyantide 2008-08-28 17:14 發(fā)表評論
]]>
java字符編碼轉(zhuǎn)換研究(轉(zhuǎn)帖)http://www.aygfsteel.com/cyantide/archive/2008/08/26/224420.htmlcyantidecyantideTue, 26 Aug 2008 02:50:00 GMThttp://www.aygfsteel.com/cyantide/archive/2008/08/26/224420.htmlhttp://www.aygfsteel.com/cyantide/comments/224420.htmlhttp://www.aygfsteel.com/cyantide/archive/2008/08/26/224420.html#Feedback0http://www.aygfsteel.com/cyantide/comments/commentRss/224420.htmlhttp://www.aygfsteel.com/cyantide/services/trackbacks/224420.htmljava字符編碼轉(zhuǎn)換研究

1. 概述

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

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

2. 編碼基本知識

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

2.1. iso8859-1

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

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

2.2. GB2312/GBK

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

2.3. unicode

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

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

2.4. UTF

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

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

3. java對字符的處理

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

3.1. getBytes(charset)

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

3.2. new String(charset)

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

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

3.3. setCharacterEncoding()

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

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

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

3.4. 處理過程

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

3.4.1. 表單輸入

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

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

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

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

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

3.4.2. 文件編譯

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

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

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

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

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

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

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

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

3.5. 幾處設(shè)置

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

3.5.1. jsp編譯

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

3.5.2. jsp輸出

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

3.5.3. meta設(shè)置

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

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

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

3.5.4. form設(shè)置

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

4. 系統(tǒng)軟件

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

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

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

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

4.2. apache

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

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

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

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

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

4.4. 其它

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

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

5. URL地址

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

5.1. URL編碼

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

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

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

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

5.2. rewrite

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

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

5.3. URLEncode.encode()

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

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

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

5.4. 一個解決方案

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

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

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

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

       int lLen=b.length,lCharCount=0;

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

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

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

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

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

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

              if(i+lCount>lLen) return false;

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

       }

       return true;

}

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

public static String getUrlParam(String aStr,String aDefaultCharset)

throws UnsupportedEncodingException{

       if(aStr==null) return null;

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

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

}

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

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

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

有一個例子可以證明google也遇到了上述問題,而且也采用了和上述相似的處理方法,比如,如果在地址欄中輸入"

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

6. 其它

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

6.1. SecureCRT

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

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

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

6.2. 過濾器

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

6.3. POST和GET

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

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

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

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

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

 



cyantide 2008-08-26 10:50 發(fā)表評論
]]>
java中的系統(tǒng)屬性以及環(huán)境變量(轉(zhuǎn)帖)http://www.aygfsteel.com/cyantide/archive/2008/08/15/222228.htmlcyantidecyantideFri, 15 Aug 2008 06:04:00 GMThttp://www.aygfsteel.com/cyantide/archive/2008/08/15/222228.htmlhttp://www.aygfsteel.com/cyantide/comments/222228.htmlhttp://www.aygfsteel.com/cyantide/archive/2008/08/15/222228.html#Feedback0http://www.aygfsteel.com/cyantide/comments/commentRss/222228.htmlhttp://www.aygfsteel.com/cyantide/services/trackbacks/222228.html從概念上講,系統(tǒng)屬性環(huán)境變量 都是名稱與值之間的映射。兩種機(jī)制都能用來將用戶定義的信息傳遞給 Java 進(jìn)程。環(huán)境變量產(chǎn)生更多的全局效應(yīng),因為它們不僅對Java 子進(jìn)程可見,而且對于定義它們的進(jìn)程的所有子進(jìn)程都是可見的。在不同的操作系統(tǒng)上,它們的語義有細(xì)微的差別,比如,不區(qū)分大小寫。因為這些原因,環(huán)境變量更可能有意料不到的副作用。最好在可能的地方使用系統(tǒng)屬性。環(huán)境變量應(yīng)該在需要全局效應(yīng)的時候使用,或者在外部系統(tǒng)接口要求使用環(huán)境變量時使用(比如 PATH)。

代碼如下:

//import java.util.*;
import java.util.Properties;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;

public class GetSysPropertiesAndEnv
{
 public static void main(String [] args)
 {
  //獲取所有系統(tǒng)屬性
   Properties prpt = System.getProperties();
   Enumeration enm = prpt.propertyNames();  //返回系統(tǒng)屬性列表中所有鍵的枚舉
   String key = "";
   System.out.println("當(dāng)前系統(tǒng)屬性如下:=========");
   while(enm.hasMoreElements())
  {
   key = (String) enm.nextElement();
   System.out.println(key+":"+System.getProperty(key,"undefined"));
  }

  //獲取所有環(huán)境變量的設(shè)置
   Map map = System.getenv();       //返回系統(tǒng)環(huán)境變量的字符串映射視圖。
   Set  set  = map.keySet();        //返回映射中包含的鍵的 set 視圖
   System.out.println("當(dāng)前環(huán)境變量如下:=========");
   Iterator itr = set.iterator();
   while(itr.hasNext())
  {
   key = (String) itr.next();
   System.out.println(key+":"+map.get(key));
  }
 }
}

其中個人認(rèn)為比較重要的系統(tǒng)屬性如下:

java.home:Java 安裝目錄 (比如D:\JavaStudio\jdk15\jre)
java.class.path:Java 類路徑
java.vm.version:Java虛擬機(jī)版本號(比如:1.5.0-b64)
java.version:Java版本號(比如:1.5.0)

os.name:操作系統(tǒng)的名稱(比如:Windows XP)
os.version:操作系統(tǒng)的版本(比如:Windows XP 的版本為5.1)

user.home:用戶的主目錄 (比如:C:\Documents and Settings\zhangsan)
user.name:當(dāng)前用戶名
user.country:當(dāng)前用戶所屬國家
user.dir:用戶的當(dāng)前工作目錄

比較重要的環(huán)境變量(Windows操作系統(tǒng)):

%COMPUTERNAME%     返回計算機(jī)的名稱。
%COMSPEC%     返回命令行解釋器可執(zhí)行程序的準(zhǔn)確路徑。

%WINDIR%    返回操作系統(tǒng)目錄的位置。
%OS%     返回操作系統(tǒng)的名稱。Windows 2000 將操作系統(tǒng)顯示為 Windows_NT。
%PATH%    指定可執(zhí)行文件的搜索路徑。

%USERDOMAIN%    返回包含用戶帳戶的域的名稱。
%USERNAME%    返回當(dāng)前登錄的用戶的名稱。



cyantide 2008-08-15 14:04 發(fā)表評論
]]>
JAVA的util包(轉(zhuǎn)帖)http://www.aygfsteel.com/cyantide/archive/2008/07/09/213528.htmlcyantidecyantideWed, 09 Jul 2008 02:02:00 GMThttp://www.aygfsteel.com/cyantide/archive/2008/07/09/213528.htmlhttp://www.aygfsteel.com/cyantide/comments/213528.htmlhttp://www.aygfsteel.com/cyantide/archive/2008/07/09/213528.html#Feedback0http://www.aygfsteel.com/cyantide/comments/commentRss/213528.htmlhttp://www.aygfsteel.com/cyantide/services/trackbacks/213528.htmlJavaTM 2 Platform
Standard Ed. 5.0


         在JAVA的util包中有兩個所有集合的父接口Collection和Map,它們的父子關(guān)系:


           java.util
        +Collection 這個接口extends自 --java.lang.Iterable接口
           +List 接口
              -ArrayList 類
              -LinkedList 類
              -Vector 類     此類是實現(xiàn)同步的


           +Queue 接口
              +不常用,在此不表.


           +Set 接口
              +SortedSet 接口
                 -TreeSet 類
              -HashSet


        +Map 接口
          -HashMap 類 (除了不同步和允許使用 null 鍵/值之外,與 Hashtable 大致相同.)
          -Hashtable 類 此類是實現(xiàn)同步的,不允許使用 null 鍵值
          +SortedMap 接口
             -TreeMap 類


          以下對眾多接口和類的簡單說明:首先不能不先說一下數(shù)組(Array)
       
一、Array , Arrays


Java所有“存儲及隨機(jī)訪問一連串對象”的做法,array是最有效率的一種。


1、
效率高,但容量固定且無法動態(tài)改變。
array還有一個缺點(diǎn)是,無法判斷其中實際存有多少元素,length只是告訴我們array的容量。


2、Java中有一個Arrays類,專門用來操作array。
       arrays中擁有一組static函數(shù),
equals():比較兩個array是否相等。array擁有相同元素個數(shù),且所有對應(yīng)元素兩兩相等。
fill():將值填入array中。
sort():用來對array進(jìn)行排序。
binarySearch():在排好序的array中尋找元素。
System.arraycopy():array的復(fù)制。



二、Collection , Map


若撰寫程序時不知道究竟需要多少對象,需要在空間不足時自動擴(kuò)增容量,則需要使用容器類庫,array不適用。


1、Collection 和 Map 的區(qū)別


容器內(nèi)每個為之所存儲的元素個數(shù)不同。
Collection類型者,每個位置只有一個元素。
Map類型者,持有 key-value pair,像個小型數(shù)據(jù)庫。


2、Java2容器類類庫的用途是“保存對象”,它分為兩類,各自旗下的子類關(guān)系


Collection
       --List:將以特定次序存儲元素。所以取出來的順序可能和放入順序不同。
             --ArrayList / LinkedList / Vector
       --Set : 不能含有重復(fù)的元素
             --HashSet /TreeSet
Map
       --HashMap
    --HashTable
    --TreeMap


 Map----一組成對的“鍵值對”對象,即其元素是成對的對象,最典型的應(yīng)用就是數(shù)據(jù)字典,并且還有其它廣泛的應(yīng)用。另外,Map可以返回其所
有鍵組成的Set和其所有值組成的Collection,或其鍵值對組成的Set,并且還可以像數(shù)組一樣擴(kuò)展多維Map,只要讓Map中鍵值對的每個“值
”是一個Map即可。

 Collection下 1.迭代器

  迭代器是一種設(shè)計模式,它是一個對象,它可以遍歷并選擇序列中的對象,而開發(fā)人員不需要了解該序列的底層結(jié)構(gòu)。迭代器通常被稱為“輕量級”對象,因為創(chuàng)建它的代價小。

  Java中的Iterator功能比較簡單,并且只能單向移動:

  (1) 使用方法iterator()要求容器返回一個Iterator。第一次調(diào)用Iterator的next()方法時,它返回序列的第一個元素。注意:iterator()方法是java.lang.Iterable接口,被Collection繼承。


  (2) 使用next()獲得序列中的下一個元素。

  (3) 使用hasNext()檢查序列中是否還有元素。

  (4) 使用remove()將迭代器新返回的元素刪除。

  Iterator是Java迭代器最簡單的實現(xiàn),為List設(shè)計的ListIterator具有更多的功能,它可以從兩個方向遍歷List,也可以從List中插入和刪除元素。

  2.List的功能方法

 
 List(interface):
次序是List最重要的特點(diǎn);它確保維護(hù)元素特定的順序。List為Collection添加了許多方法,使得能夠向List中間插入與移除元素(只推薦
LinkedList使用)。一個List可以生成ListIterator,使用它可以從兩個方向遍歷List,也可以從List中間插入和刪除元素。

  ArrayList: 由數(shù)組實現(xiàn)的List。它允許對元素進(jìn)行快速隨機(jī)訪問,但是向List中間插入與移除元素的速度很慢。ListIterator只應(yīng)該用來由后向前遍歷ArrayList,而不是用來插入和刪除元素,因為這比LinkedList開銷要大很多。

 
 LinkedList:
由列表實現(xiàn)的List。對順序訪問進(jìn)行了優(yōu)化,向List中間插入與刪除得開銷不大,隨機(jī)訪問則相對較慢(可用ArrayList代替)。它具有方法
addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast(),這些方
法(沒有在任何接口或基類中定義過)使得LinkedList可以當(dāng)作堆棧、隊列和雙向隊列使用。

  3.Set的功能方法

 
 Set(interface):
存入Set的每個元素必須是唯一的,這也是與List不同的,因為Set不保存重復(fù)元素。加入Set的Object必須定義equals()方法以確保對
象的唯一性。Set與Collection有完全一樣的接口。Set接口不保證維護(hù)元素的次序。

  HashSet: HashSet能快速定位一個元素,存入HashSet的對象必須定義hashCode()。

  TreeSet: 保持次序的Set,底層為樹結(jié)構(gòu)。使用它可以從Set中提取有序的序列。

  LinkedHashSet: 具有HashSet的查詢速度,且內(nèi)部使用鏈表維護(hù)元素的順序(插入的次序)。于是在使用迭代器遍歷Set時,結(jié)果會按元素插入的次序顯示。

 
 HashSet采用散列函數(shù)對元素進(jìn)行排序,這是專門為快速查詢而設(shè)計的;TreeSet采用紅黑樹的數(shù)據(jù)結(jié)構(gòu)進(jìn)行排序元
素;LinkedHashSet內(nèi)部使用散列以加快查詢速度,同時使用鏈表維護(hù)元素的次序,使得看起來元素是以插入的順序保存的。需要注意的是,生成自己
的類時,Set需要維護(hù)元素的存儲順序,因此要實現(xiàn)Comparable接口并定義compareTo()方法。


3、其他特征


*     List,Set,Map將持有對象一律視為Object型別。
*     Collection、List、Set、Map都是接口,不能實例化。
      繼承自它們的 ArrayList, Vector, HashTable, HashMap是具象class,這些才可被實例化。
*     vector容器確切知道它所持有的對象隸屬什么型別。vector不進(jìn)行邊界檢查。



三、Collections


Collections是針對集合類的一個幫助類。提供了一系列靜態(tài)方法實現(xiàn)對各種集合的搜索、排序、線程完全化等操作。
相當(dāng)于對Array進(jìn)行類似操作的類——Arrays。
如,Collections.max(Collection coll); 取coll中最大的元素。
       Collections.sort(List list); 對list中元素排序


四、如何選擇?


1、容器類和Array的區(qū)別、擇取
      *     容器類僅能持有對象引用(指向?qū)ο蟮闹羔槪皇菍ο笮畔opy一份至數(shù)列某位置。
      *     一旦將對象置入容器內(nèi),便損失了該對象的型別信息。


2、
     *     在各種Lists中,最好的做法是以ArrayList作為缺省選擇。當(dāng)插入、刪除頻繁時,使用LinkedList();
        Vector總是比ArrayList慢,所以要盡量避免使用。
     *     在各種Sets中,HashSet通常優(yōu)于HashTree(插入、查找)。只有當(dāng)需要產(chǎn)生一個經(jīng)過排序的序列,才用TreeSet。
        HashTree存在的唯一理由:能夠維護(hù)其內(nèi)元素的排序狀態(tài)。
     *     在各種Maps中
        HashMap用于快速查找。
     *     當(dāng)元素個數(shù)固定,用Array,因為Array效率是最高的。


結(jié)論:最常用的是ArrayList,HashSet,HashMap,Array。而且,我們也會發(fā)現(xiàn)一個規(guī)律,用TreeXXX都是排序的。



注意:


1、Collection沒有g(shù)et()方法來取得某個元素。只能通過iterator()遍歷元素。
2、Set和Collection擁有一模一樣的接口。
3、List可以通過get()方法來一次取出一個元素。使用數(shù)字來選擇一堆對象中的一個,get(0)...。(add/get)
4、一般使用ArrayList。用LinkedList構(gòu)造堆棧stack、隊列queue


5、Map用 put(k,v) / get(k),還可以使用containsKey()/containsValue()來檢查其中是否含有某個key/value。
      HashMap會利用對象的hashCode來快速找到key。
    *     hashing
          哈希碼就是將對象的信息經(jīng)過一些轉(zhuǎn)變形成一個獨(dú)一無二的int值,這個值存儲在一個array中。
          我們都知道所有存儲結(jié)構(gòu)中,array查找速度是最快的。所以,可以加速查找。
      
          發(fā)生碰撞時,讓array指向多個values。即,數(shù)組每個位置上又生成一個梿表。


6、Map中元素,可以將key序列、value序列單獨(dú)抽取出來。
使用keySet()抽取key序列,將map中的所有keys生成一個Set。
使用values()抽取value序列,將map中的所有values生成一個Collection。


為什么一個生成Set,一個生成Collection?那是因為,key總是獨(dú)一無二的,value允許重復(fù)。



cyantide 2008-07-09 10:02 發(fā)表評論
]]>
主站蜘蛛池模板: 安溪县| 特克斯县| 凌云县| 隆安县| 江油市| 昭通市| 广东省| 沿河| 新闻| 高州市| 南岸区| 墨玉县| 图木舒克市| 沙田区| 韩城市| 罗田县| 临汾市| 莱阳市| 丹江口市| 南充市| 关岭| 新野县| 巴马| 万安县| 客服| 左权县| 濉溪县| 泸西县| 花莲县| 深州市| 太和县| 崇义县| 西峡县| 高安市| 海宁市| 秦皇岛市| 霍林郭勒市| 和平区| 古浪县| 慈利县| 福建省|