ResourceBundle是java開發中非常實用的一個類,主要用來處理應用程序多語言這樣的國際化問題。
如果你的應用程序如果有國際化的需求,可以考慮使用ResourceBundle, 你要做的就是給出滿足特定格式的Properties 文件,例如
resource.propreties
resource_zh_CN.properties
resource_ja_JP.properties.
然後應用程序使用ResourceBundle.getBundle(“resource”, locale) 就可以自動的搜索的相應Locale的Properties 文件。
雖然看起來很方便,但使用起來需要注意兩個問題: 1 Properties 文件的搜索次序, 2. 決定是否能找到Properties 文件的ClassLoader , 這也是很多初學者遇到的問題
1. 搜索次序。
先來看個例子,假設你的系統只有兩個Properties
(1) resource.zh_CN.properties : 中文的Properties
(2) resource.properties : 英文的Properties
假設你Java 的default locale是zh_CN, 如果你調用 ResourceBundle.getBundle(“resource”, Locale.US) , 你覺得系統會使用哪一個文件中的內容?
很多人會覺得會使用resource.properties 中的內容, 但實際上不是這樣的,當你傳入一個Locale.US 給ResourceBundle的時候 , ResourceBundle的搜索次序是這樣:
(1) resource_en_US.properties --- 沒找到
(2) resource_en.properties --- 還是沒找到
(3) resource_zh_CN.properties ---- default locale, 找到了
(4) resource_zh_properties
(5) resource.properties
注意,ResourceBundle會自動的加上一個default locale 即 zh_CN 來搜索
系統沒有找到xxxx__en_US.properties, 也沒有找到xxx_en.properties, 而是找到了xxx_zh_CN.properties, 就會使用其中的內容, 所以你看的的是中文的結果。
實際上ResourceBundle 搜索結束以後,會建立一個ResourceBundle 對象的Chain, 對於上面的例子會是這樣:
ResourceBundle_2 [locale=zh_CN , parent = ResourceBundle_1]
ResourceBundle_1 [locale = empty parent = null]
你可能要問,這個鏈表中問什麼沒有en_US,en 和zh相關的信息? 這是因爲他們相關的Properties 不存在, 沒有必要加入這個鏈表中。
如果你的應用程序訪問resource文件的一個值得時候, 系統會先在ResourceBundle_2[Locale=zh_CN] 這個對象中找, 如果找到,直接返回相應的值
如果沒有找到,順着parent 即ResourceBundle_1繼續尋找, 如果還沒有找到,只好返回null 了, 因爲沒有parent 了
2. ClassLoader
這個也是經常出問題的地方, 很多時候當你準備好各種Locale 的Properties 文件, 調用ResourceBundle.getBundle(“resource”, Locale.US) 時,系統總是告訴你, 找不到resource_en_US的文件, 很是令人抓狂。
主要的原因就是ClassLoader 不對 ,有空接着寫 :-)