Java编程规约(OOP)
1、【強(qiáng)制】避免通過一個(gè)類的對象引用訪問此類的靜態(tài)變量或靜態(tài)方法,無謂增加編譯器解析
成本,直接用類名來訪問即可。
2、【強(qiáng)制】所有的覆寫方法,必須加@Override 注解。
說明:getObject()與 get0bject()的問題。一個(gè)是字母的 O,一個(gè)是數(shù)字的 0,加@Override 可以準(zhǔn)確判
斷是否覆蓋成功。另外,如果在抽象類中對方法簽名進(jìn)行修改,其實(shí)現(xiàn)類會馬上編譯報(bào)錯。
3、【強(qiáng)制】相同參數(shù)類型,相同業(yè)務(wù)含義,才可以使用 Java 的可變參數(shù),避免使用 Object。
說明:可變參數(shù)必須放置在參數(shù)列表的最后。(提倡同學(xué)們盡量不用可變參數(shù)編程)
正例:public List<User> listUsers(String type, Long... ids) {...}
4、【強(qiáng)制】外部正在調(diào)用或者二方庫依賴的接口,不允許修改方法簽名,避免對接口調(diào)用方產(chǎn)
生影響。接口過時(shí)必須加@Deprecated 注解,并清晰地說明采用的新接口或者新服務(wù)是什
么。
5、【強(qiáng)制】不能使用過時(shí)的類或方法。
說明:java.net.URLDecoder 中的方法 decode(String encodeStr) 這個(gè)方法已經(jīng)過時(shí),應(yīng)該使用雙參數(shù)
decode(String source, String encode)。接口提供方既然明確是過時(shí)接口,那么有義務(wù)同時(shí)提供新的接
口;作為調(diào)用方來說,有義務(wù)去考證過時(shí)方法的新實(shí)現(xiàn)是什么。
6、【強(qiáng)制】Object 的 equals 方法容易拋空指針異常,應(yīng)使用常量或確定有值的對象來調(diào)用
equals。
正例:"test".equals(object);
反例:object.equals("test");
說明:推薦使用 java.util.Objects#equals(JDK7 引入的工具類)。
7、【強(qiáng)制】所有整型包裝類對象之間值的比較,全部使用 equals 方法比較。
說明:對于 Integer var = ? 在-128 至 127 范圍內(nèi)的賦值,Integer 對象是在 IntegerCache.cache 產(chǎn)
生,會復(fù)用已有對象,這個(gè)區(qū)間內(nèi)的 Integer 值可以直接使用==進(jìn)行判斷,但是這個(gè)區(qū)間之外的所有數(shù)
據(jù),都會在堆上產(chǎn)生,并不會復(fù)用已有對象,這是一個(gè)大坑,推薦使用 equals 方法進(jìn)行判斷。
8、【強(qiáng)制】浮點(diǎn)數(shù)之間的等值判斷,基本數(shù)據(jù)類型不能用==來比較,包裝數(shù)據(jù)類型不能用
equals 來判斷。
說明:浮點(diǎn)數(shù)采用“尾數(shù)+階碼”的編碼方式,類似于科學(xué)計(jì)數(shù)法的“有效數(shù)字+指數(shù)”的表示方式。二進(jìn)制無法精確表示大部分的十進(jìn)制小數(shù)。
反例:
 float a = 1.0f - 0.9f; float b = 0.9f - 0.8f;
 if (a == b) {
 // 預(yù)期進(jìn)入此代碼快,執(zhí)行其它業(yè)務(wù)邏輯 // 但事實(shí)上 a==b的結(jié)果為 false
 }
 Float x = Float.valueOf(a);?
 Float y = Float.valueOf(b);?
 if (x.equals(y)) {
 // 預(yù)期進(jìn)入此代碼快,執(zhí)行其它業(yè)務(wù)邏輯 // 但事實(shí)上 equals的結(jié)果為 false
 }
 ?
正例:
 (1) 指定一個(gè)誤差范圍,兩個(gè)浮點(diǎn)數(shù)的差值在此范圍之內(nèi),則認(rèn)為是相等的。
 float a = 1.0f - 0.9f; float b = 0.9f - 0.8f; float diff = 1e-6f;
 if (Math.abs(a - b) < diff) {
 ?System.out.println("true"); }
 (2) 使用 BigDecimal 來定義值,再進(jìn)行浮點(diǎn)數(shù)的運(yùn)算操作。
 BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
BigDecimal c = new BigDecimal("0.8");
 BigDecimal x = a.subtract(b); BigDecimal y = b.subtract(c);
 if (x.equals(y)) { }
9、關(guān)于基本數(shù)據(jù)類型與包裝數(shù)據(jù)類型的使用標(biāo)準(zhǔn)如下:
1) 【強(qiáng)制】所有的 POJO 類屬性必須使用包裝數(shù)據(jù)類型。
2) 【強(qiáng)制】RPC 方法的返回值和參數(shù)必須使用包裝數(shù)據(jù)類型。
3) 【推薦】所有的局部變量使用基本數(shù)據(jù)類型。
說明:POJO 類屬性沒有初值是提醒使用者在需要使用時(shí),必須自己顯式地進(jìn)行賦值,任何 NPE 問題,或
者入庫檢查,都由使用者來保證。
正例:數(shù)據(jù)庫的查詢結(jié)果可能是 null,因?yàn)樽詣硬鹣?#xff0c;用基本數(shù)據(jù)類型接收有 NPE 風(fēng)險(xiǎn)。
反例:比如顯示成交總額漲跌情況,即正負(fù) x%,x 為基本數(shù)據(jù)類型,調(diào)用的 RPC 服務(wù),調(diào)用不成功時(shí),
返回的是默認(rèn)值,頁面顯示為 0%,這是不合理的,應(yīng)該顯示成中劃線。所以包裝數(shù)據(jù)類型的 null 值,能
夠表示額外的信息,如:遠(yuǎn)程調(diào)用失敗,異常退出。
10、【強(qiáng)制】定義 DO/DTO/VO 等 POJO 類時(shí),不要設(shè)定任何屬性默認(rèn)值。
反例:POJO 類的 createTime 默認(rèn)值為 new Date(),但是這個(gè)屬性在數(shù)據(jù)提取時(shí)并沒有置入具體值,在
更新其它字段時(shí)又附帶更新了此字段,導(dǎo)致創(chuàng)建時(shí)間被修改成當(dāng)前時(shí)間。
11、【強(qiáng)制】序列化類新增屬性時(shí),請不要修改 serialVersionUID 字段,避免反序列失敗;如果
完全不兼容升級,避免反序列化混亂,那么請修改 serialVersionUID 值。
說明:注意 serialVersionUID 不一致會拋出序列化運(yùn)行時(shí)異常。
12、【強(qiáng)制】構(gòu)造方法里面禁止加入任何業(yè)務(wù)邏輯,如果有初始化邏輯,請放在 init 方法中。
13、【強(qiáng)制】POJO 類必須寫 toString 方法。使用 IDE 中的工具:source> generate toString
時(shí),如果繼承了另一個(gè) POJO 類,注意在前面加一下 super.toString。
說明:在方法執(zhí)行拋出異常時(shí),可以直接調(diào)用 POJO 的 toString()方法打印其屬性值,便于排查問題。
14、【強(qiáng)制】禁止在 POJO 類中,同時(shí)存在對應(yīng)屬性 xxx 的 isXxx()和 getXxx()方法。
說明:框架在調(diào)用屬性 xxx 的提取方法時(shí),并不能確定哪個(gè)方法一定是被優(yōu)先調(diào)用到。
15、【推薦】使用索引訪問用 String 的 split 方法得到的數(shù)組時(shí),需做最后一個(gè)分隔符后有無內(nèi)
容的檢查,否則會有拋 IndexOutOfBoundsException 的風(fēng)險(xiǎn)。
說明:
String str = "a,b,c,,"; String[] ary = str.split(",");
// 預(yù)期大于 3,結(jié)果是 3 System.out.println(ary.length);
16、【推薦】當(dāng)一個(gè)類有多個(gè)構(gòu)造方法,或者多個(gè)同名方法,這些方法應(yīng)該按順序放置在一起,
便于閱讀,此條規(guī)則優(yōu)先于下一條。
17、【推薦】 類內(nèi)方法定義的順序依次是:公有方法或保護(hù)方法 > 私有方法 > getter / setter
方法。
說明:公有方法是類的調(diào)用者和維護(hù)者最關(guān)心的方法,首屏展示最好;保護(hù)方法雖然只是子類關(guān)心,也可
能是“模板設(shè)計(jì)模式”下的核心方法;而私有方法外部一般不需要特別關(guān)心,是一個(gè)黑盒實(shí)現(xiàn);因?yàn)槌休d
的信息價(jià)值較低,所有 Service 和 DAO 的 getter/setter 方法放在類體最后。
?
18、【推薦】setter 方法中,參數(shù)名稱與類成員變量名稱一致,this.成員名 = 參數(shù)名。在
getter/setter 方法中,不要增加業(yè)務(wù)邏輯,增加排查問題的難度。
反例:
public Integer getData() {
?if (condition) {
return this.data + 100; } else {
?return this.data - 100;
}
}
19、【推薦】循環(huán)體內(nèi),字符串的連接方式,使用 StringBuilder 的 append 方法進(jìn)行擴(kuò)展。
說明:下例中,反編譯出的字節(jié)碼文件顯示每次循環(huán)都會 new 出一個(gè) StringBuilder 對象,然后進(jìn)行
append 操作,最后通過 toString 方法返回 String 對象,造成內(nèi)存資源浪費(fèi)。
反例:
String str = "start";
for (int i = 0; i < 100; i++) {
str = str + "hello"; }
20、【推薦】final 可以聲明類、成員變量、方法、以及本地變量,下列情況使用 final 關(guān)鍵字:
1) 不允許被繼承的類,如:String 類。
2) 不允許修改引用的域?qū)ο蟆?/span>
3) 不允許被覆寫的方法,如:POJO 類的 setter 方法。
4) 不允許運(yùn)行過程中重新賦值的局部變量。
5) 避免上下文重復(fù)使用一個(gè)變量,使用 final 可以強(qiáng)制重新定義一個(gè)變量,方便更好地進(jìn)行重構(gòu)。
21、【推薦】慎用 Object 的 clone 方法來拷貝對象。
說明:對象 clone 方法默認(rèn)是淺拷貝,若想實(shí)現(xiàn)深拷貝需覆寫 clone 方法實(shí)現(xiàn)域?qū)ο蟮纳疃缺闅v式拷貝。
22、【推薦】類成員與方法訪問控制從嚴(yán):
1) 如果不允許外部直接通過 new 來創(chuàng)建對象,那么構(gòu)造方法必須是 private。
2) 工具類不允許有 public 或 default 構(gòu)造方法。
3) 類非 static 成員變量并且與子類共享,必須是 protected。
4) 類非 static 成員變量并且僅在本類使用,必須是 private。
5) 類 static 成員變量如果僅在本類使用,必須是 private。
6) 若是 static 成員變量,考慮是否為 final。
7) 類成員方法只供類內(nèi)部調(diào)用,必須是 private。
8) 類成員方法只對繼承類公開,那么限制為 protected。
說明:任何類、方法、參數(shù)、變量,嚴(yán)控訪問范圍。過于寬泛的訪問范圍,不利于模塊解耦。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的Java编程规约(OOP)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: leetcode647 回文子串
- 下一篇: 先序中序数组推后序数组
