版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、前言阿里巴巴Java 開(kāi)發(fā)手冊(cè)是阿里巴巴集團(tuán)技術(shù)團(tuán)隊(duì)的集體智慧結(jié)晶和經(jīng)驗(yàn)總結(jié),經(jīng)歷了多次大規(guī)模一線(xiàn)實(shí)戰(zhàn)的檢驗(yàn)及不斷完善,系統(tǒng)化地整理成冊(cè),回饋給廣大開(kāi)發(fā)者?,F(xiàn)代軟件行業(yè)的高速發(fā)展對(duì)開(kāi)發(fā)者的綜合素質(zhì)要求越來(lái)越高,因?yàn)椴粌H是編程知識(shí)點(diǎn),其它維度的知識(shí)點(diǎn)也會(huì)影響到軟件的最終交付質(zhì)量。比如:數(shù)據(jù)庫(kù)的表結(jié)構(gòu)和索引設(shè)計(jì)缺陷可能帶來(lái)軟件上的架構(gòu)缺陷或性能風(fēng)險(xiǎn);工程結(jié)構(gòu)混亂導(dǎo)致后續(xù)維護(hù)艱難;沒(méi)有鑒權(quán)的漏洞代碼易被攻擊等等。所以本手冊(cè)以Java 開(kāi)發(fā)者為中心視角,劃分為編程規(guī)約、異常日志、單元測(cè)試、安全規(guī)約、MySQL 數(shù)據(jù)庫(kù)、工程結(jié)構(gòu)、設(shè)計(jì)規(guī)約七個(gè)維度,再根據(jù)內(nèi)容特征,細(xì)分成若干二級(jí)子目錄。根據(jù)約束力強(qiáng)弱及故
2、障敏感性,規(guī)約依次分為強(qiáng)制、推薦、參考三大類(lèi)。對(duì)于規(guī)約條目的延伸信息中,“說(shuō)明”對(duì)規(guī)約做了適當(dāng)擴(kuò)展和解釋?zhuān)弧罢碧岢裁礃拥木幋a和實(shí)現(xiàn)方式;“反例”說(shuō)明需要提防的雷區(qū),以及真實(shí)的錯(cuò)誤案例。本手冊(cè)的旨在碼出高效,碼出質(zhì)量?,F(xiàn)代軟件架構(gòu)的復(fù)雜性需要協(xié)同開(kāi)發(fā)完成,如何高效地協(xié)同呢?無(wú)規(guī)矩不成方圓,無(wú)規(guī)范難以協(xié)同,比如,制訂交通法規(guī)表面上是要限制行車(chē)權(quán),實(shí)際上是保障公眾的人身安全,試想如果沒(méi)有限速,沒(méi)有紅綠燈,誰(shuí)還敢上路行駛。對(duì)軟件來(lái)說(shuō),適當(dāng)?shù)囊?guī)范和標(biāo)準(zhǔn)絕不是消滅代碼內(nèi)容的創(chuàng)造性、優(yōu)雅性,而是限制過(guò)度個(gè)性化,以一種普遍認(rèn)可的統(tǒng)一方式一起做事,提升協(xié)作效率,降低溝通成本。代碼的字里行間流淌的是軟件系統(tǒng)
3、的血液,質(zhì)量的提升是盡可能少踩坑,杜絕踩重復(fù)的坑,切實(shí)提升系統(tǒng)穩(wěn)定性,碼出質(zhì)量??紤]到可以零距離地與眾多開(kāi)發(fā)同學(xué)進(jìn)行互動(dòng),決定未來(lái)在線(xiàn)維護(hù)手冊(cè)內(nèi)容,此 1.4.0 的 PDF 版本,是最為詳盡的版本,新增設(shè)計(jì)規(guī)約大章節(jié),并增加若干條目;我們已經(jīng)在 2017 杭州云棲大會(huì)上發(fā)布了阿里巴巴Java 開(kāi)發(fā)規(guī)約插件(點(diǎn)此下載),阿里云效(一站式企業(yè)協(xié)同研發(fā)云)也集成了代碼規(guī)約掃描引擎。最后,碼出高效阿里巴巴Java 開(kāi)發(fā)手冊(cè)詳解即將,敬請(qǐng)關(guān)注。目錄(一)(二)(三)(四)(五)(六)(七)(八)(九)命名風(fēng)格1常量定義3代碼格式4OOP 規(guī)約6集合處理9并發(fā)處理12控制語(yǔ)句14注釋規(guī)約16其它18二、
4、異常日志19(一)(二)異常處理19日志規(guī)約20(一)(二)(三)(四)建表規(guī)約25索引規(guī)約26SQL 語(yǔ)句28ORM 映射29六、工程結(jié)構(gòu)31(一)(二)(三)應(yīng)用分層31二方庫(kù)依賴(lài)32服務(wù)器33七、設(shè)計(jì)規(guī)約35附 1:版本歷史37附 2:專(zhuān)有名詞解釋38(注:瀏覽時(shí)請(qǐng)使用 PDF 左側(cè)導(dǎo)航欄)三、單元測(cè)試22四、安全規(guī)約24五、MySQL 數(shù)據(jù)庫(kù)25前言一、編程規(guī)約1 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)Java 開(kāi)發(fā)手冊(cè)一、編程規(guī)約(一) 命名風(fēng)格1. 【強(qiáng)制】代碼中的命名均不能以下劃線(xiàn)或美元符號(hào)開(kāi)始,也不能以下劃線(xiàn)或美元符號(hào)結(jié)束。反 例 :_name / name / $name / name
5、_ / name$ / name 2. 【強(qiáng)制】代碼中的命名嚴(yán)禁使用拼音與英文混合的方式,更不允許直接使用中文的方式。說(shuō)明:正確的英文拼寫(xiě)和語(yǔ)法可以讓閱讀者易于理解,避免歧義。注意,即使純拼音命名方式也要避免采用。正例:alibaba / taobao / youku / hangzhou 等國(guó)際通用的名稱(chēng),可視同英文。反例:DaZhePromotion 打折 / getPingfenByName() 評(píng)分 /int 某變量 = 33. 【強(qiáng)制】類(lèi)名使用 UpperCamelCase 風(fēng)格,但以下情形例外:DOPO / UID 等。/ BO / DTO / VO / AO /正例:MarcoP
6、olo /反例:macroPolo /UserDO /UserDo /XmlService /XMLService /TcpUdpDeal /TCPUDPDeal /TaPromotionTAPromotion4. 【強(qiáng)制】方法名、參數(shù)名、成員變量、局部變量都統(tǒng)一使用 lowerCamelCase 風(fēng)格,必須遵從駝峰形式。正例: localValue / getHttpMessage() / inputUserId5. 【強(qiáng)制】常量命名全部大寫(xiě),單詞間用下劃線(xiàn)隔開(kāi),力求語(yǔ)義表達(dá)完整清楚,不要嫌名字長(zhǎng)。正例:MAX_STOCK_COUNT反例:MAX_COUNT6. 【強(qiáng)制】抽象類(lèi)命名使用 Ab
7、stract 或 Base 開(kāi)頭;異常類(lèi)命名使用 Exception 結(jié)尾;測(cè)試類(lèi)命名以它要測(cè)試的類(lèi)的名稱(chēng)開(kāi)始,以 Test 結(jié)尾。7. 【強(qiáng)制】類(lèi)型與中括號(hào)緊挨相連來(lái)表示數(shù)組。正例:定義整形數(shù)組 int arrayDemo;反例:在 main 參數(shù)中,使用 String args來(lái)定義。8. 【強(qiáng)制】POJO 類(lèi)中布爾類(lèi)型的變量,都不要加 is 前綴,否則部分框架解析會(huì)引起序列化錯(cuò)誤。反例:定義為基本數(shù)據(jù)類(lèi)型 Boolean isDeleted 的屬性,它的方法也是 isDeleted(),RPC1/38版本號(hào)制定團(tuán)隊(duì)更新日期備注1.4.0阿里巴巴集團(tuán)技術(shù)團(tuán)隊(duì)2018.5.20增加設(shè)計(jì)規(guī)約(
8、詳盡版) 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)框架在反向解析的時(shí)候,“誤以為”對(duì)應(yīng)的屬性名稱(chēng)是 deleted,導(dǎo)致屬性獲取不到,進(jìn)而拋出異常。9. 【強(qiáng)制】包名統(tǒng)一使用小寫(xiě),點(diǎn)分隔符之間有且僅有一個(gè)自然語(yǔ)義的英語(yǔ)單詞。包名統(tǒng)一使用單數(shù)形式,但是類(lèi)名如果有復(fù)數(shù)含義,類(lèi)名可以使用復(fù)數(shù)形式。正例:應(yīng)用工具類(lèi)包名為 com.alibaba.ai.util、類(lèi)名為 MessageUtils(此規(guī)則參考 spring的框架結(jié)構(gòu))10. 【強(qiáng)制】杜絕完全不規(guī)范的縮寫(xiě),避免望文不知義。反例:AbstractClass“縮寫(xiě)”命名成 AbsClass;condition“縮寫(xiě)”命名成 condi,此類(lèi)隨意縮寫(xiě)嚴(yán)重降低
9、了代碼的可閱讀性。11. 【推薦】為了達(dá)到代碼自解釋的目標(biāo),任何自定義編程元素在命名時(shí),使用盡量完整的單詞組合來(lái)表達(dá)其意。正例:在 JDK 中,表達(dá)原子更新的類(lèi)名為:AtomicReferenceFieldUpdater。反例:變量 int a 的隨意命名方式。12.【推薦】如果模塊、接口、類(lèi)、方法使用了設(shè)計(jì)模式,在命名時(shí)需體現(xiàn)出具體模式。說(shuō)明:將設(shè)計(jì)模式體現(xiàn)在名字中,有利于閱讀者快速理解架構(gòu)設(shè)計(jì)理念。正例:public class OrderFactory;public class LoginProxy; public class ResourceObserver;13. 【推薦】接口類(lèi)中的
10、方法和屬性不要加任何修飾符號(hào)(public 也不要加),保持代碼的簡(jiǎn)潔性,并加上有效的 Javadoc 注釋。盡量不要在接口里定義變量,如果一定要定義變量,肯定是與接口方法相關(guān),并且是整個(gè)應(yīng)用的基礎(chǔ)常量。正例:接口方法簽名 void commit();接口基礎(chǔ)常量 String COMPANY = alibaba;反例:接口方法定義 public abstract void f();說(shuō)明:JDK8 中接口允許有默認(rèn)實(shí)現(xiàn),那么這個(gè) default 方法,是對(duì)所有實(shí)現(xiàn)類(lèi)都有價(jià)值的默認(rèn)實(shí)現(xiàn)。14. 接口和實(shí)現(xiàn)類(lèi)的命名有兩套規(guī)則:1) 【強(qiáng)制】對(duì)于 Service 和 DAO 類(lèi),基于 SOA 的理念
11、,暴露出來(lái)的服務(wù)一定是接口,內(nèi)部的實(shí)現(xiàn)類(lèi)用 Impl 的后綴與接口區(qū)別。正例:CacheServiceImpl 實(shí)現(xiàn) CacheService 接口。2) 【推薦】如果是形容能力的接口名稱(chēng),取對(duì)應(yīng)的形容詞為接口名(通常是able 的形式) 。正例:AbstractTranslator 實(shí)現(xiàn) Translatable 接口。2/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)15. 【參考】枚舉類(lèi)名建議帶上 Enum 后綴,枚舉成員名稱(chēng)需要全大寫(xiě),單詞間用下劃線(xiàn)隔開(kāi)。說(shuō)明:枚舉其實(shí)就是特殊的類(lèi),域成員均為常量,且構(gòu)造方法被默認(rèn)強(qiáng)制是私有。正例:枚舉名字為 ProcessStatusEnum 的成員名稱(chēng):SUC
12、CESS / UNKNOWN_REASON。16. 【參考】各層命名規(guī)約:Service/DAO 層方法命名規(guī)約A)1)2)3)4)5)6)獲取單個(gè)對(duì)象的方法用 get 做前綴。獲取多個(gè)對(duì)象的方法用 list 做前綴,復(fù)數(shù)形式結(jié)尾如:listObjects。獲取統(tǒng)計(jì)值的方法用 count 做前綴。插入的方法用 save/insert 做前綴。刪除的方法用 remove/delete 做前綴。修改的方法用 update 做前綴。B)領(lǐng)域模型命名規(guī)約1)2)3)4)數(shù)據(jù)對(duì)象:xxxDO,xxx 即為數(shù)據(jù)表名。數(shù)據(jù)傳輸對(duì)象:xxxDTO,xxx 為業(yè)務(wù)領(lǐng)域相關(guān)的名稱(chēng)。展示對(duì)象:xxxVO,xxx 一
13、般為網(wǎng)頁(yè)名稱(chēng)。POJO 是 DO/DTO/BO/VO 的統(tǒng)稱(chēng),禁止命名成 xxxPOJO。(二) 常量定義1. 【強(qiáng)制】不允許任何魔法值(即未經(jīng)預(yù)先定義的常量)直接出現(xiàn)在代碼中。反例:String key = Id#taobao_ + tradeId;cache.put(key, value);2. 【強(qiáng)制】在 long 或者 Long 賦值時(shí),數(shù)值后使用大寫(xiě)的 L,不能是小寫(xiě)的 l,小寫(xiě)容易跟數(shù)字1 混淆,造成誤解。說(shuō)明:Long a = 2l; 寫(xiě)的是數(shù)字的 21,還是 Long 型的 2?3. 【推薦】不要使用一個(gè)常量類(lèi)維護(hù)所有常量,要按常量功能進(jìn)行歸類(lèi),分開(kāi)維護(hù)。說(shuō)明:大而全的常量類(lèi),
14、雜亂無(wú)章,使用查找功能才能定位到修改的常量,不利于理解和維護(hù)。正例:緩存相關(guān)常量放在類(lèi) CacheConsts 下;系統(tǒng)配置相關(guān)常量放在類(lèi) ConfigConsts 下。4. 【推薦】常量的復(fù)用層次有五層:跨應(yīng)用共享常量、應(yīng)用內(nèi)共享常量、子工程內(nèi)共享常量、包內(nèi)共享常量、類(lèi)內(nèi)共享常量。1) 跨應(yīng)用共享常量:放置在二方庫(kù)中,通常是 client.jar 中的 constant 目錄下。2) 應(yīng)用內(nèi)共享常量:放置在一方庫(kù)中,通常是子模塊中的 constant 目錄下。反例:易懂變量也要統(tǒng)一定義成應(yīng)用內(nèi)共享常量,兩位攻城師在兩個(gè)類(lèi)中分別定義了表示“是”的變量:類(lèi) A 中:public static f
15、inal String YES = yes;3/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)類(lèi) B 中 :public static final String YES = y; A.YES.equals(B.YES),預(yù)期是 true,但實(shí)際返回為 false,導(dǎo)致線(xiàn)上問(wèn)題。3)4)5)子工程內(nèi)部共享常量:即在當(dāng)前子工程的 constant 目錄下。包內(nèi)共享常量:即在當(dāng)前包下單獨(dú)的 constant 目錄下。類(lèi)內(nèi)共享常量:直接在類(lèi)內(nèi)部 private static final 定義。5. 【推薦】如果變量值僅在一個(gè)固定范圍內(nèi)變化用 enum 類(lèi)型來(lái)定義。說(shuō)明:如果存在名稱(chēng)之外的延伸屬性應(yīng)使用 enum
16、類(lèi)型,下面正例中的數(shù)字就是延伸信息,表示一年中的第幾個(gè)季節(jié)。正例:public enum SeasonEnum SPRING(1), SUMMER(2), AUTUMN(3), WINTER(4);private int seq; SeasonEnum(int seq)this.seq = seq;(三) 代碼格式1. 【強(qiáng)制】大括號(hào)的使用約定。如果是大括號(hào)內(nèi)為空,則簡(jiǎn)潔地寫(xiě)成即可,不需要換行;如果是非空代碼塊則:1)2)3)4)左大括號(hào)前不換行。左大括號(hào)后換行。 右大括號(hào)前換行。右大括號(hào)后還有 else 等代碼則不換行;表示終止的右大括號(hào)后必須換行。2. 【強(qiáng)制】左小括號(hào)和字符之間不出現(xiàn)空格
17、;同樣,右小括號(hào)和字符之間也不出現(xiàn)空格;而左大括號(hào)前需要空格。詳見(jiàn)第 5 條下方正例提示。反例:if (a = b)3. 【強(qiáng)制】if/for/while/switch/do 等保留字與括號(hào)之間都必須加空格。4. 【強(qiáng)制】任何二目、三目運(yùn)算符的左右兩邊都需要加一個(gè)空格。說(shuō)明:運(yùn)算符包括賦值運(yùn)算符=、邏輯運(yùn)算符&、加減乘除符號(hào)等。5. 【強(qiáng)制】采用 4 個(gè)空格縮進(jìn),禁止使用 tab 字符。說(shuō)明:如果使用 tab 縮進(jìn),必須設(shè)置 1 個(gè) tab 為 4 個(gè)空格。IDEA 設(shè)置 tab 為 4 個(gè)空格時(shí), 請(qǐng)勿勾選 Use tab character;而在 eclipse 中,必須勾選 insert
18、 spaces for tabs。4/38空格空格 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)正例: (涉及 1-5 點(diǎn))public static void main(String args) / 縮進(jìn) 4 個(gè)空格String say = hello;/ 運(yùn)算符的左右必須有一個(gè)空格int flag = 0;/ 關(guān)鍵詞 if 與括號(hào)之間必須有一個(gè)空格,括號(hào)內(nèi)的 f 與左括號(hào),0 與右括號(hào)不需要空格if (flag = 0) System.out.println(say);/ 左大括號(hào)前加空格且不換行;左大括號(hào)后換行if (flag = 1) System.out.println(world);/ 右大括號(hào)前
19、換行,右大括號(hào)后有 else,不用換行 else System.out.println(ok);/ 在右大括號(hào)后直接結(jié)束,則必須換行6. 【強(qiáng)制】注釋的雙斜線(xiàn)與注釋內(nèi)容之間有且僅有一個(gè)空格。正例:/ 這是示例注釋?zhuān)?qǐng)注意在雙斜線(xiàn)之后有一個(gè)空格String ygb = new String();7. 【強(qiáng)制】單行字符數(shù)限制不超過(guò) 120 個(gè),超出需要換行,換行時(shí)遵循如下原則:1)2)3)4)5)第二行相對(duì)第一行縮進(jìn) 4 個(gè)空格,從第三行開(kāi)始,不再繼續(xù)縮進(jìn),參考示例。運(yùn)算符與下文一起換行。方法調(diào)用的點(diǎn)符號(hào)與下文一起換行。方法調(diào)用中的多個(gè)參數(shù)需要換行時(shí),在逗號(hào)后進(jìn)行。在括號(hào)前不要換行,見(jiàn)反例。正例:
20、StringBuffer sb = new StringBuffer();/ 超過(guò) 120 個(gè)字符的情況下,換行縮進(jìn) 4 個(gè)空格,點(diǎn)號(hào)和方法名稱(chēng)一起換行sb.append(zi).append(xin).append(huang).append(huang).append(huang);反例:StringBuffer sb = new StringBuffer();/ 超過(guò) 120 個(gè)字符的情況下,不要在括號(hào)前換行sb.append(zi).append(xin).append (huang);/ 參數(shù)很多的方法調(diào)用可能超過(guò) 120 個(gè)字符,不要在逗號(hào)前換行method(args1, args
21、2, args3, ., argsX);5/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)8. 【強(qiáng)制】方法參數(shù)在定義和傳入時(shí),多個(gè)參數(shù)逗號(hào)后邊必須加空格。正例:下例中實(shí)參的 args1,后邊必須要有一個(gè)空格。method(args1, args2, args3);9. 【強(qiáng)制】IDE 的 text file encoding 設(shè)置為 UTF-8; IDE 中文件的換行符使用 Unix 格式, 不要使用 Windows 格式。10. 【推薦】單個(gè)方法的總行數(shù)不超過(guò) 80 行。說(shuō)明:包括方法簽名、結(jié)束右大括號(hào)、方法內(nèi)代碼、注釋、空行、回車(chē)及任何不可見(jiàn)字符的總行數(shù)不超過(guò) 80 行。正例:代碼邏輯分清紅花和綠葉
22、,個(gè)性和共性,綠葉邏輯單獨(dú)出來(lái)成為額外方法,使主干代碼更加清晰;共性邏輯抽取成為共性方法,便于復(fù)用和維護(hù)。11. 【推薦】沒(méi)有必要增加若干空格來(lái)使某一行的字符與上一行對(duì)應(yīng)位置的字符對(duì)齊。正例:int one = 1; long two = 2L;float three = 3F;StringBuffer sb = new StringBuffer();說(shuō)明:增加 sb 這個(gè)變量,如果需要對(duì)齊,則給 a、b、c 都要增加幾個(gè)空格,在變量比較多的情況下,是非常累贅的事情。12. 【推薦】不同邏輯、不同語(yǔ)義、不同業(yè)務(wù)的代碼之間插入一個(gè)空行分隔開(kāi)來(lái)以提升可讀性。說(shuō)明:任何情形,沒(méi)有必要插入多個(gè)空行進(jìn)行
23、隔開(kāi)。(四) OOP 規(guī)約1. 【強(qiáng)制】避免通過(guò)一個(gè)類(lèi)的對(duì)象引用訪(fǎng)問(wèn)此類(lèi)的靜態(tài)變量或靜態(tài)方法,無(wú)謂增加編譯器解析成本,直接用類(lèi)名來(lái)訪(fǎng)問(wèn)即可。2. 【強(qiáng)制】所有的覆寫(xiě)方法,必須加Override 注解。說(shuō)明:getObject()與 get0bject()的問(wèn)題。一個(gè)是字母的 O,一個(gè)是數(shù)字的 0,加Override 可以準(zhǔn)確判斷是否覆蓋成功。另外,如果在抽象類(lèi)中對(duì)方法簽名進(jìn)行修改,其實(shí)現(xiàn)類(lèi)會(huì)馬上編譯報(bào)錯(cuò)。3. 【強(qiáng)制】相同參數(shù)類(lèi)型,相同業(yè)務(wù)含義,才可以使用 Java 的可變參數(shù),避免使用 Object。說(shuō)明:可變參數(shù)必須放置在參數(shù)列表的最后。(提倡同學(xué)們盡量不用可變參數(shù)編程)正例:public
24、 List listUsers(String type, Long. ids) .4. 【強(qiáng)制】外部正在調(diào)用或者二方庫(kù)依賴(lài)的接口,不允許修改方法簽名,避免對(duì)接口調(diào)用方產(chǎn)生影響。接口過(guò)時(shí)必須加Deprecated 注解,并清晰地說(shuō)明采用的新接口或者新服務(wù)是什么。5. 【強(qiáng)制】不能使用過(guò)時(shí)的類(lèi)或方法。說(shuō)明:.URLDecoder 中的方法 decode(String encodeStr) 這個(gè)方法已經(jīng)過(guò)時(shí),應(yīng)6/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)該使用雙參數(shù) decode(String source, String encode)。接口提供方既然明確是過(guò)時(shí)接口, 那么有義務(wù)同時(shí)提供
25、新的接口;作為調(diào)用方來(lái)說(shuō),有義務(wù)去考證過(guò)時(shí)方法的新實(shí)現(xiàn)是什么。6. 【強(qiáng)制】Object 的 equals 方法容易拋空指針異常,應(yīng)使用常量或確定有值的對(duì)象來(lái)調(diào)用equals。正例:test.equals(object); 反例:object.equals(test);說(shuō)明:推薦使用 java.util.Objects#equals(JDK7 引入的工具類(lèi))7. 【強(qiáng)制】所有的相同類(lèi)型的包裝類(lèi)對(duì)象之間值的比較,全部使用 equals 方法比較。說(shuō)明:對(duì)于 Integer var = ? 在-128 至 127 范圍內(nèi)的賦值,Integer 對(duì)象是在IntegerCache.cache 產(chǎn)生,會(huì)
26、復(fù)用已有對(duì)象,這個(gè)區(qū)間內(nèi)的 Integer 值可以直接使用=進(jìn)行判斷,但是這個(gè)區(qū)間之外的所有數(shù)據(jù),都會(huì)在堆上產(chǎn)生,并不會(huì)復(fù)用已有對(duì)象,這是一個(gè)大坑, 推薦使用 equals 方法進(jìn)行判斷。8. 關(guān)于基本數(shù)據(jù)類(lèi)型與包裝數(shù)據(jù)類(lèi)型的使用標(biāo)準(zhǔn)如下:1)2)3)【強(qiáng)制】所有的 POJO 類(lèi)屬性必須使用包裝數(shù)據(jù)類(lèi)型?!緩?qiáng)制】RPC 方法的返回值和參數(shù)必須使用包裝數(shù)據(jù)類(lèi)型。【推薦】所有的局部變量使用基本數(shù)據(jù)類(lèi)型。說(shuō)明:POJO 類(lèi)屬性沒(méi)有初值是提醒使用者在需要使用時(shí),必須自己顯式地進(jìn)行賦值,任何NPE 問(wèn)題,或者入庫(kù)檢查,都由使用者來(lái)保證。正例:數(shù)據(jù)庫(kù)的查詢(xún)結(jié)果可能是 null,因?yàn)樽詣?dòng)拆箱,用基本數(shù)據(jù)類(lèi)型
27、接收有 NPE 風(fēng)險(xiǎn)。反例:比如顯示成交總額漲跌情況,即正負(fù) x%,x 為基本數(shù)據(jù)類(lèi)型,調(diào)用的 RPC 服務(wù),調(diào)用不成功時(shí),返回的是默認(rèn)值,頁(yè)面顯示為 0%,這是不合理的,應(yīng)該顯示成中劃線(xiàn)。所以包裝數(shù)據(jù)類(lèi)型的 null 值,能夠表示額外的信息,如:遠(yuǎn)程調(diào)用失敗,異常退出。9. 【強(qiáng)制】定義 DO/DTO/VO 等 POJO 類(lèi)時(shí),不要設(shè)定任何屬性默認(rèn)值。反例:POJO 類(lèi)的 gmtCreate 默認(rèn)值為 new Date(),但是這個(gè)屬性在數(shù)據(jù)提取時(shí)并沒(méi)有置入具體值,在更新其它字段時(shí)又附帶更新了此字段,導(dǎo)致創(chuàng)建時(shí)間被修改成當(dāng)前時(shí)間。10. 【強(qiáng)制】序列化類(lèi)新增屬性時(shí),請(qǐng)不要修改 serialV
28、ersionUID 字段,避免反序列失??;如果完全不兼容升級(jí),避免反序列化混亂,那么請(qǐng)修改 serialVersionUID 值。說(shuō)明:注意 serialVersionUID 不一致會(huì)拋出序列化運(yùn)行時(shí)異常。11. 【強(qiáng)制】構(gòu)造方法里面禁止加入任何業(yè)務(wù)邏輯,如果有初始化邏輯,請(qǐng)放在 init 方法中。12. 【強(qiáng)制】POJO 類(lèi)必須寫(xiě) toString 方法。使用 IDE 中的工具:source generate toString時(shí),如果繼承了另一個(gè) POJO 類(lèi),注意在前面加一下 super.toString。說(shuō)明:在方法執(zhí)行拋出異常時(shí),可以直接調(diào)用 POJO 的 toString()方法打印
29、其屬性值,便于排查問(wèn)題。7/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)13. 【強(qiáng)制】禁止在 POJO 類(lèi)中,同時(shí)存在對(duì)應(yīng)屬性 xxx 的 isXxx()和 getXxx()方法。說(shuō)明:框架在調(diào)用屬性 xxx 的提取方法時(shí),并不能確定哪個(gè)方法一定是被優(yōu)先調(diào)用到。14. 【推薦】使用索引訪(fǎng)問(wèn)用 String 的 split 方法得到的數(shù)組時(shí),需做最后一個(gè)分隔符后有無(wú)內(nèi)容的檢查,否則會(huì)有拋 IndexOutOfBoundsException 的風(fēng)險(xiǎn)。說(shuō)明:String str = a,b,c,;String ary = str.split(,);/ 預(yù) 期 大 于 3, 結(jié) 果 是 3 System.ou
30、t.println(ary.length);15. 【推薦】當(dāng)一個(gè)類(lèi)有多個(gè)構(gòu)造方法,或者多個(gè)同名方法,這些方法應(yīng)該按順序放置在一起, 便于閱讀,此條規(guī)則優(yōu)先于第 16 條規(guī)則。16. 【推薦】 類(lèi)內(nèi)方法定義的順序依次是:公有方法或保護(hù)方法 私有方法 getter/setter方法。說(shuō)明:公有方法是類(lèi)的調(diào)用者和維護(hù)者最關(guān)心的方法,首屏展示最好;保護(hù)方法雖然只是子類(lèi)關(guān)心,也可能是“模板設(shè)計(jì)模式”下的核心方法;而私有方法外部一般不需要特別關(guān)心,是一個(gè)黑盒實(shí)現(xiàn);因?yàn)槌休d的信息價(jià)值較低,所有 Service 和 DAO 的 getter/setter 方法放在類(lèi)體最后。17. 【推薦】setter 方法
31、中,參數(shù)名稱(chēng)與類(lèi)成員變量名稱(chēng)一致,this.成員名 = 參數(shù)名。在getter/setter 方法中,不要增加業(yè)務(wù)邏輯,增加排查問(wèn)題的難度。反例:public Integer getData() if (condition) return this.data + 100; else return this.data - 100;18. 【推薦】循環(huán)體內(nèi),字符串的連接方式,使用 StringBuilder 的 append 方法進(jìn)行擴(kuò)展。說(shuō)明:下例中,反編譯出的字節(jié)碼文件顯示每次循環(huán)都會(huì) new 出一個(gè) StringBuilder 對(duì)象, 然后進(jìn)行 append 操作,最后通過(guò) toString
32、 方法返回 String 對(duì)象,造成內(nèi)存資源浪費(fèi)。反例:String str = start;for (int i = 0; i 100; i+) str = str + hello;19. 【推薦】final 可以聲明類(lèi)、成員變量、方法、以及本地變量,下列情況使用 final 關(guān)鍵字:1)2)3)不允許被繼承的類(lèi),如:String 類(lèi)。不允許修改引用的域?qū)ο蟆2辉试S被重寫(xiě)的方法,如:POJO 類(lèi)的setter 方法。8/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)4) 不允許運(yùn)行過(guò)程中重新賦值的局部變量。5) 避免上下文重復(fù)使用一個(gè)變量,使用 final 描述可以強(qiáng)制重新定義一個(gè)變量,方便更好地進(jìn)行重
33、構(gòu)。20. 【推薦】慎用 Object 的 clone 方法來(lái)拷貝對(duì)象。說(shuō)明:對(duì)象的 clone 方法默認(rèn)是淺拷貝,若想實(shí)現(xiàn)深拷貝需要重寫(xiě) clone 方法實(shí)現(xiàn)域?qū)ο蟮纳疃缺闅v式拷貝。21. 【推薦】類(lèi)成員與方法訪(fǎng)問(wèn)控制從嚴(yán):1)2)3)4)5)6)7)8)如果不允許外部直接通過(guò) new 來(lái)創(chuàng)建對(duì)象,那么構(gòu)造方法必須是 private。工具類(lèi)不允許有 public 或 default 構(gòu)造方法。類(lèi)非 static 成員變量并且與子類(lèi)共享,必須是 protected。類(lèi)非 static 成員變量并且僅在本類(lèi)使用,必須是 private。類(lèi) static 成員變量如果僅在本類(lèi)使用,必須是 priv
34、ate。若是 static 成員變量,考慮是否為 final。類(lèi)成員方法只供類(lèi)內(nèi)部調(diào)用,必須是 private。類(lèi)成員方法只對(duì)繼承類(lèi)公開(kāi),那么限制為 protected。說(shuō)明:任何類(lèi)、方法、參數(shù)、變量,嚴(yán)控訪(fǎng)問(wèn)范圍。過(guò)于寬泛的訪(fǎng)問(wèn)范圍,不利于模塊解耦。思考:如果是一個(gè) private 的方法,想刪除就刪除,可是一個(gè) public 的 service 成員方法或成員變量,刪除一下,不得手心冒點(diǎn)汗嗎?變量像自己的小孩,盡量在自己的視線(xiàn)內(nèi),變量作用域太大,無(wú)限制的到處跑,那么你會(huì)擔(dān)心的。(五) 集合處理1. 【強(qiáng)制】關(guān)于 hashCode 和 equals 的處理,遵循如下規(guī)則:1) 只要重寫(xiě) eq
35、uals,就必須重寫(xiě) hashCode。2) 因?yàn)?Set 存儲(chǔ)的是不重復(fù)的對(duì)象,依據(jù) hashCode 和 equals 進(jìn)行判斷,所以 Set 存儲(chǔ)的對(duì)象必須重寫(xiě)這兩個(gè)方法。3) 如果自定義對(duì)象作為 Map 的鍵,那么必須重寫(xiě) hashCode 和 equals。說(shuō)明:String 重寫(xiě)了hashCode 和 equals 方法,所以我們可以非常愉快地使用 String 對(duì)象作為 key 來(lái)使用。2. 【強(qiáng)制】ArrayList 的subList 結(jié)果不可強(qiáng)轉(zhuǎn)成ArrayList,否則會(huì)拋出ClassCastException異常,即 java.util.RandomAccessSubLi
36、stcannot be cast to java.util.ArrayList 。說(shuō)明:subList 返回的是 ArrayList 的內(nèi)部類(lèi) SubList,并不是 ArrayList 而是 ArrayList的一個(gè)視圖,對(duì)于 SubList 子列表的所有操作最終會(huì)反映到原列表上。3. 【強(qiáng)制】在 subList 場(chǎng)景中,高度注意對(duì)原集合元素的增加或刪除,均會(huì)導(dǎo)致子列表的遍歷、增加、刪除產(chǎn)生 ConcurrentModificationException 異常。9/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)4. 【強(qiáng)制】使用集合轉(zhuǎn)數(shù)組的方法,必須使用集合的 toArray(T array),傳入的是
37、類(lèi)型完全一樣的數(shù)組,大小就是 list.size()。說(shuō)明:使用 toArray 帶參方法,入?yún)⒎峙涞臄?shù)組空間不夠大時(shí),toArray 方法內(nèi)部將重新分配內(nèi)存空間,并返回新數(shù)組地址;如果數(shù)組元素個(gè)數(shù)大于實(shí)際所需,下標(biāo)為 list.size() 的數(shù)組元素將被置為 null,其它數(shù)組元素保持原值,因此最好將方法入?yún)?shù)組大小定義與集合元素個(gè)數(shù)一致。正例:List list = new ArrayList(2); list.add(guan);list.add(bao);String array = new Stringlist.size(); array = list.toArray(array)
38、;反例:直接使用 toArray 無(wú)參方法存在問(wèn)題,此方法返回值只能是 Object類(lèi),若強(qiáng)轉(zhuǎn)其它類(lèi)型數(shù)組將出現(xiàn) ClassCastException 錯(cuò)誤。5. 【強(qiáng)制】使用工具類(lèi) Arrays.asList()把數(shù)組轉(zhuǎn)換成集合時(shí),不能使用其修改集合相關(guān)的方法,它的 add/remove/clear 方拋出 UnsupportedOperationException 異常。說(shuō)明:asList 的返回對(duì)象是一個(gè) Arrays 內(nèi)部類(lèi),并沒(méi)有實(shí)現(xiàn)集合的修改方法。Arrays.asList體現(xiàn)的是適配器模式,只是轉(zhuǎn)換接口,的數(shù)據(jù)仍是數(shù)組。String str = new String you, w
39、u ; List list = Arrays.asList(str);第一種情況:list.add(yangguanbao); 運(yùn)行時(shí)異常。第二種情況:str0 = gujin; 那么 list.get(0)也會(huì)隨之修改。6. 【強(qiáng)制】泛型通配符來(lái)接收返回的數(shù)據(jù),此寫(xiě)法的泛型集合不能使用 add 方法,而不能使用 get 方法,作為接口調(diào)用賦值時(shí)易出錯(cuò)。說(shuō)明:擴(kuò)展說(shuō)一下 PECS(Producer Extends Consumer Super)原則:第一、頻繁往外讀取內(nèi)容的,適合用。第二、經(jīng)常往里插入的,適合用。7. 【強(qiáng)制】不要在 foreach 循環(huán)里進(jìn)行元素的remove/add 操作。
40、remove 元素請(qǐng)使用 Iterator方式,如果并發(fā)操作,需要對(duì) Iterator 對(duì)象加鎖。正例:List list = new ArrayList(); list.add(1);list.add(2);Iterator iterator = list.iterator(); while (iterator.hasNext() String item = iterator.next(); if (刪除元素的條件) iterator.remove();10/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)反例:for (String item : list) if (1.equals(item) lis
41、t.remove(item);說(shuō)明:以上代碼的執(zhí)行結(jié)果肯定會(huì)出乎大家的意料,那么試一下把“1”換成“2”,會(huì)是同樣的結(jié)果嗎?8. 【強(qiáng)制】 在 JDK7 版本及以上,Comparator 實(shí)現(xiàn)類(lèi)要滿(mǎn)足如下三個(gè)條件,不然 Arrays.sort, Collections.sort 會(huì)報(bào) IllegalArgumentException 異常。說(shuō)明:三個(gè)條件如下1)2)3)x,y 的比較結(jié)果和 y,x 的比較結(jié)果相反。xy,yz,則xz。x=y,則x,z 比較結(jié)果和 y,z 比較結(jié)果相同。反例:下例中沒(méi)有處理相等的情況,實(shí)際使用中可能會(huì)出現(xiàn)異常:new Comparator() Overridep
42、ublic int compare(Student o1, Student o2) return o1.getId() o2.getId() ? 1 : -1;9. 【推薦】集合泛型定義時(shí),在 JDK7 及以上,使用 diamond 語(yǔ)法或全省略。說(shuō)明:菱形泛型,即 diamond,直接使用來(lái)指代前邊已經(jīng)指定的類(lèi)型。正例:/ diamond 方式HashMap userCache = new HashMap(16);/ 全省略方式ArrayList users = new ArrayList(10);10. 【推薦】集合初始化時(shí),指定集合初始值大小。說(shuō)明:HashMap 使用 HashMap(
43、int initialCapacity) 初始化。正例:initialCapacity = (需要存儲(chǔ)的元素個(gè)數(shù) / 負(fù)載因子) + 1。注意負(fù)載因子(即 loader factor)默認(rèn)為 0.75,如果暫時(shí)無(wú)法確定初始值大小,請(qǐng)?jiān)O(shè)置為 16(即默認(rèn)值)。反例:HashMap 需要放置 1024 個(gè)元素,由于沒(méi)有設(shè)置容量初始大小,隨著元素不斷增加,容量 7 次被迫擴(kuò)大,resize 需要重建 hash 表,嚴(yán)重影響性能。11. 【推薦】使用 entrySet 遍歷 Map 類(lèi)集合KV,而不是 keySet 方式進(jìn)行遍歷。說(shuō)明:keySet 其實(shí)是遍歷了 2 次,一次是轉(zhuǎn)為 Iterator
44、對(duì)象,另一次是從 hashMap 中取出key 所對(duì)應(yīng)的 value。而 entrySet 只是遍歷了一次就把 key 和 value 都放到了 entry 中,效合對(duì)象;keySet()返回的是 K 值集合,是一個(gè) Set 集合對(duì)象;entrySet()返回的是 K-V 值組合集合。11/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)12. 【推薦】高度注意 Map 類(lèi)集合 K/V 能不能存儲(chǔ) null 值的情況,如下表格:反例: 由于 HashMap 的干擾,很多人認(rèn)為 ConcurrentHashMap 是可以置入 null 值,而事實(shí)上, 存儲(chǔ) null 值時(shí)會(huì)拋出 NPE 異常。13. 【參考】
45、合理利用好集合的有序性(sort)和穩(wěn)定性(order),避免集合的無(wú)序性(unsort)和不穩(wěn)定性(unorder)帶來(lái)的影響。說(shuō)明:有序性是指遍歷的結(jié)果是按某種比較規(guī)則依次排列的。穩(wěn)定性指集合每次遍歷的元素次序是一定的。如:ArrayList 是 order/unsort;HashMap 是 unorder/unsort;TreeSet 是order/sort。14. 【參考】利用 Set 元素唯一的特性,可以快速對(duì)一個(gè)集合進(jìn)行去重操作,避免使用 List 的contains 方法進(jìn)行遍歷、對(duì)比、去重操作。(六) 并發(fā)處理1. 【強(qiáng)制】獲取單例對(duì)象需要保證線(xiàn)程安全,其中的方法也要保證線(xiàn)程安
46、全。說(shuō)明:資源驅(qū)動(dòng)類(lèi)、工具類(lèi)、單例工廠(chǎng)類(lèi)都需要注意。2. 【強(qiáng)制】創(chuàng)建線(xiàn)程或線(xiàn)程池時(shí)請(qǐng)指定有意義的線(xiàn)程名稱(chēng),方便出錯(cuò)時(shí)回溯。正例:public class TimerTaskThread extends Thread public TimerTaskThread() super.setName(TimerTaskThread);.3. 【強(qiáng)制】線(xiàn)程資源必須通過(guò)線(xiàn)程池提供,不允許在應(yīng)用中自行顯式創(chuàng)建線(xiàn)程。說(shuō)明:使用線(xiàn)程池的好處是減少在創(chuàng)建和銷(xiāo)毀線(xiàn)程上所消耗的時(shí)間以及系統(tǒng)資源的開(kāi)銷(xiāo),解決資源不足的問(wèn)題。如果不使用線(xiàn)程池,有可能造成系統(tǒng)創(chuàng)建大量同類(lèi)線(xiàn)程而導(dǎo)致消耗完內(nèi)存或者“過(guò)度切換”的問(wèn)題。12/3
47、8集合類(lèi)KeyValueSuper說(shuō)明Hashtable不允許為 null不允許為 nullDictionary線(xiàn)程安全ConcurrentHashMap不允許為 null不允許為 nullAbstractMap鎖分段技術(shù)(JDK8:CAS)TreeMap不允許為 null允許為 nullAbstractMap線(xiàn)程不安全HashMap允許為 null允許為 nullAbstractMap線(xiàn)程不安全 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)4. 【強(qiáng)制】線(xiàn)程池不允許使用 Executors 去創(chuàng)建,而是通過(guò) ThreadPoolExecutor 的方式,這樣的處理方式讓寫(xiě)的同學(xué)更加明確線(xiàn)程池的運(yùn)行規(guī)則,規(guī)避
48、資源耗盡的風(fēng)險(xiǎn)。說(shuō)明:Executors 返回的線(xiàn)程池對(duì)象的弊端如下:1) FixedThreadPool 和 SingleThreadPool:允許的請(qǐng)求隊(duì)列長(zhǎng)度為 Integer.MAX_VALUE,可能會(huì)堆積大量的請(qǐng)求,從而導(dǎo)致 OOM。2) CachedThreadPool 和 ScheduledThreadPool:允許的創(chuàng)建線(xiàn)程數(shù)量為 Integer.MAX_VALUE,可能會(huì)創(chuàng)建大量的線(xiàn)程,從而導(dǎo)致 OOM。5. 【強(qiáng)制】SimpleDateFormat 是線(xiàn)程不安全的類(lèi),一般不要定義為 static 變量,如果定義為static,必須加鎖,或者使用 DateUtils 工具類(lèi)。
49、正例:注意線(xiàn)程安全,使用 DateUtils。亦推薦如下處理:private static final ThreadLocal df = new ThreadLocal() Overrideprotected DateFormat initialValue() return new SimpleDateFormat(yyyy-MM-dd);說(shuō)明:如果是 JDK8 的應(yīng)用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat,immutable thread-safe。給出的解釋?zhuān)?/p>
50、simple beautiful strong6. 【強(qiáng)制】高并發(fā)時(shí),同步調(diào)用應(yīng)該去考量鎖的性能損耗。能用無(wú)鎖數(shù)據(jù)結(jié)構(gòu),就不要用鎖;能鎖區(qū)塊,就不要鎖整個(gè)方法體;能用對(duì)象鎖,就不要用類(lèi)鎖。說(shuō)明:盡可能使加鎖的代碼塊工作量盡可能的小,避免在鎖代碼塊中調(diào)用 RPC 方法。7. 【強(qiáng)制】對(duì)多個(gè)資源、數(shù)據(jù)庫(kù)表、對(duì)象同時(shí)加鎖時(shí),需要保持一致的加鎖順序,否則可能會(huì)造成死鎖。說(shuō)明:線(xiàn)程一需要對(duì)表 A、B、C 依次全部加鎖后才可以進(jìn)行更新操作,那么線(xiàn)程二的加鎖順序也必須是 A、B、C,否則可能出現(xiàn)死鎖。8. 【強(qiáng)制】并發(fā)修改同一記錄時(shí),避免更新丟失,需要加鎖。要么在應(yīng)用層加鎖,要么在緩存加鎖,要么在數(shù)據(jù)庫(kù)層使
51、用樂(lè)觀鎖,使用 version 作為更新依據(jù)。說(shuō)明:如果每次訪(fǎng)問(wèn)沖突概率小于 20%,推薦使用樂(lè)觀鎖,否則使用悲觀鎖。樂(lè)觀鎖的重試次數(shù)不得小于 3 次。9. 【強(qiáng)制】多線(xiàn)程并行處理定時(shí)任務(wù)時(shí),Timer 運(yùn)行多個(gè) TimeTask 時(shí),只要其中之一沒(méi)有捕獲拋出的異常,其它任務(wù)便會(huì)自動(dòng)終止運(yùn)行,使用 ScheduledExecutorService 則沒(méi)有這個(gè)問(wèn)題。10. 【推薦】使用 CountDownLatch 進(jìn)行異步轉(zhuǎn)同步操作,每個(gè)線(xiàn)程退出前必須調(diào)用 countDown 方法,線(xiàn)程執(zhí)行代碼注意 catch 異常,確保 countDown 方法被執(zhí)行到,避免主線(xiàn)程無(wú)法執(zhí)行至 await 方
52、法,直到超時(shí)才返回結(jié)果。說(shuō)明:注意,子線(xiàn)程拋出異常堆棧,不能在主線(xiàn)程 try-catch 到。13/38 阿里巴巴 Java 開(kāi)發(fā)手冊(cè)11. 【推薦】避免 Random 實(shí)例被多線(xiàn)程使用,雖然共享該實(shí)例是線(xiàn)程安全的,但會(huì)因競(jìng)爭(zhēng)同一seed 導(dǎo)致的性能下降。說(shuō)明:Random 實(shí)例包括 java.util.Random 的實(shí)例或者 Math.random()的方式。正例:在 JDK7 之后,可以直接使用 API ThreadLocalRandom,而在 JDK7 之前,需要編碼保證每個(gè)線(xiàn)程持有一個(gè)實(shí)例。12. 【推薦】在并發(fā)場(chǎng)景下,通過(guò)雙重檢查鎖(double-checked locking)實(shí)
53、現(xiàn)延遲初始化的優(yōu)化問(wèn)題隱患(可參考 The Double-Checked Locking is Broken Declaration),推薦解決方案中較為簡(jiǎn)單一種(適用于 JDK5 及以上版本),將目標(biāo)屬性聲明為 volatile 型。反例:class LazyInitDemo private Helper helper = null; public Helper getHelper() if (helper = null) synchronized(this) if (helper = null)helper = new Helper();return helper;/ other meth
54、ods and fields.13. 【參考】volatile 解決多線(xiàn)程內(nèi)存不可見(jiàn)問(wèn)題。對(duì)于一寫(xiě)多讀,是可以解決變量同步問(wèn)題, 但是如果多寫(xiě),同樣無(wú)法解決線(xiàn)程安全問(wèn)題。如果是 count+操作,使用如下類(lèi)實(shí)現(xiàn): AtomicInteger count = new AtomicInteger(); count.addAndGet(1); 如果是 JDK8,推薦使用 LongAdder 對(duì)象,比 AtomicLong 性能更好(減少樂(lè)觀鎖的重試次數(shù))。14. 【參考】 HashMap 在容量不夠進(jìn)行 resize 時(shí)由于高并發(fā)可能出現(xiàn)死鏈,導(dǎo)致 CPU 飆升,在開(kāi)發(fā)過(guò)程中可以使用其它數(shù)據(jù)結(jié)構(gòu)或加鎖來(lái)規(guī)避此風(fēng)險(xiǎn)。15. 【參考】ThreadLocal 無(wú)法解決共享對(duì)象的更新問(wèn)題,ThreadLocal 對(duì)象建議使用 static 修飾。這
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 安徽省宣城市旌德縣2026屆九年級(jí)上學(xué)期期末質(zhì)量檢測(cè)語(yǔ)文試卷(含答案)
- 2025-2026學(xué)年河北省邢臺(tái)市威縣李寨中學(xué)九年級(jí)(上)期末數(shù)學(xué)試卷(含簡(jiǎn)略答案)
- 圍棋分段題庫(kù)及答案
- 2022~2023房屋建筑施工人員考試題庫(kù)及答案第636期
- 四年級(jí)奧數(shù)巧算乘除法
- 鋼結(jié)構(gòu)安裝工培訓(xùn)課程要點(diǎn)
- 2022新部編版三年級(jí)下冊(cè)《道德與法治》期末模擬考試(附答案)
- 2026屆黑龍江省龍江教育聯(lián)盟高三上學(xué)期期末考試歷史試題(含答案)
- 食源性疾病考試卷及答案
- 上海工會(huì)考試試題及答案
- 郵政服務(wù)操作流程與規(guī)范(標(biāo)準(zhǔn)版)
- 2025年年輕人生活方式洞察報(bào)告-海惟智庫(kù)
- 2026昆山鈔票紙業(yè)有限公司校園招聘15人備考題庫(kù)及1套完整答案詳解
- 2026年重慶市江津區(qū)社區(qū)專(zhuān)職人員招聘(642人)考試參考題庫(kù)及答案解析
- 新華資產(chǎn)招聘筆試題庫(kù)2026
- 造口常用護(hù)理用品介紹
- 小米銷(xiāo)售新人培訓(xùn)
- 礦山復(fù)工培訓(xùn)課件
- 華為校招硬件筆試題目及答案
- 部編版小學(xué)語(yǔ)文六年級(jí)下冊(cè)必讀書(shū)閱讀訓(xùn)練試題及答案(全冊(cè))
- 精神衛(wèi)生機(jī)構(gòu)護(hù)理人力資源配置措施
評(píng)論
0/150
提交評(píng)論