您的位置:本站首頁-JAVA指導(dǎo)-JAVA字符謎題8:字符串奶酪
下面的程序從一個字節(jié)序列創(chuàng)建了一個字符串,然后迭代遍歷字符串中的字符,并將它們作為數(shù)字打印。請描述一下程序打印出來的數(shù)字序列:public class StringCheese { public static void main(String[] args) { byte bytes[] = new byte[256]; for (int i = 0; i < 256; i++) bytes[i] = (byte)i; String str = new String(bytes); for (int i = 0, n = str.length(); i < n; i++) System.out.println((int)str.charAt(i) + " "); } }首先,byte數(shù)組用從0到255每一個可能的byte數(shù)值進行了初始化,然后這些byte數(shù)值通過String構(gòu)造器被轉(zhuǎn)換成了char數(shù)值。最后,char數(shù)值被轉(zhuǎn)型為int數(shù)值并被打印。打印出來的數(shù)值肯定是非負整數(shù),因為char數(shù)值是無符號的,因此,你可能期望該程序?qū)错樞虼蛴〕?到255的整數(shù)。
如果你運行該程序,可能會看到這樣的序列。但是在運行一次,可能看到的就不是這個序列了。我們在四臺機器上運行它,會看到四個不同的序列,包括前面描述的那個序列。這個程序甚至都不能保證會正常終止,比打印其他任何特定字符串都要缺乏這種保證。它的行為完全是不確定的。
這里的罪魁禍首就是String(byte[])構(gòu)造器。有關(guān)它的規(guī)范描述道:“在通過解碼使用平臺缺省字符集的指定byte數(shù)組來構(gòu)造一個新的String時,該新String的長度是字符集的一個函數(shù),因此,它可能不等于byte數(shù)組的長度。當給定的所有字節(jié)在缺省字符集中并非全部有效時,這個構(gòu)造器的行為是不確定的”[ Java -API]。
到底什么是字符集?從技術(shù)角度上講,它是“被編碼的字符集合和字符編碼模式的結(jié)合物”[Java-API]。換句話說,字符集是一個包,包含了字符、表示字符的數(shù)字編碼以及在字符編碼序列和字節(jié)序列之間來回轉(zhuǎn)換的方式。轉(zhuǎn)換模式在字符集之間存在著很大的區(qū)別:某些是在字符和字節(jié)之間做一對一的映射,但是大多數(shù)都不是這樣。ISO-8859-1是唯一能夠讓該程序按順序打印從0到255的整數(shù)的缺省字符集,它更為大家所熟知的名字是Latin-1[ISO-8859-1]。
J2SE運行期環(huán)境(JRE)的缺省字符集依賴于底層的操作系統(tǒng)和語言。如果你想知道你的JRE的缺省字符集,并且你使用的是5.0或更新的版本,那么你可以通過調(diào)用java.nio.charset.Charset.defaultCharset()來了解。如果你使用的是較早的版本,那么你可以通過閱讀系統(tǒng)屬性“file.encoding”來了解。
幸運的是,你沒有被強制要求必須去容忍各種稀奇古怪的缺省字符集。當你在char序列和byte序列之間做轉(zhuǎn)換時,你可以且通常是應(yīng)該顯式地指定字符集。除了接受byte數(shù)字之外,還可以接受一個字符集名稱的String構(gòu)造器就是專為此目的而設(shè)計的。如果你用下面的構(gòu)造器去替換在最初的程序中的String構(gòu)造器,那么不管缺省的字符集是什么,該程序都保證能夠按照順序打印從0到255的整數(shù):
String str = new String(bytes, "ISO-8859-1");這個構(gòu)造器聲明會拋出UnsupportedEncodingException異常,因此你必須捕獲它,或者更適宜的方式是聲明main方法將拋出它,要不然程序不能通過編譯。盡管如此,該程序?qū)嶋H上不會拋出異常。Charset的規(guī)范要求Java平臺的每一種實現(xiàn)都要支持某些種類的字符集,ISO-8859-1就位列其中。
這個謎題的教訓(xùn)是:每當你要將一個byte序列轉(zhuǎn)換成一個String時,你都在使用某一個字符集,不管你是否顯式地指定了它。如果你想讓你的程序的行為是可預(yù)知的,那么就請你在每次使用字符集時都明確地指定。對API的設(shè)計者來說,提供這么一個依賴于缺省字符集的String(byte[])構(gòu)造器可能并非是一個好主意。
posted on 2007-04-24 12:03 sooxin 閱讀(201) 評論(0) 編輯 收藏 所屬分類: JAVA