Java開發規範之OOP規約篇(上)

開發規範是所有程序員開發過程中必須掌握的技能,早期的軟件開發過程可能不重視開發規範導致後期維護成本極高,現在國內的大廠都會制定自己的開發規範,完善的開發規範不僅可以提高團隊效率,還可以避免很多意外的bug問題。下面我找了幾篇關於代碼規範重要性的文章,大家可以參考下。

  1. 爲什麼谷歌要執行嚴格的代碼編寫規範
  2. 爲什麼要寫軟件開發規範?軟件開發規範書怎麼寫?
  3. 爲什麼在程序開發中要注意編碼規範?(知乎問答)

本系列文章將整合 阿里巴巴《Java開發手冊》 和  谷歌《Java編程規範》 ,總結Java開發過程的編碼規範,並通過具體編碼案例給出編碼規範的原因,如果總結內容存在問題還望指出。


Java開發規範之OOP規約篇共上中下三篇,具體內容參考 阿里巴巴《Java開發手冊》的目錄,同時補充 谷歌《Java編程規範》的內容,阿里巴巴規約內容比較豐富,谷歌規約很多實際內容都沒有。

  1. Java開發規範之OOP規約篇(上)
  2. Java開發規範之OOP規約篇(中)
  3. Java開發規範之OOP規約篇(下)

Java開發規範之OOP規約篇(

1.直接使用類名訪問靜態變量或靜態方法

2.覆寫方法必須加@Override註解

3.Java可變參數必須是相同參數和業務含義且避免使用Object類型

4.禁止修改調用或者二方庫依賴的接口方法簽名

5.禁止使用過時的類或方法

6.使用常量或確定有值的對象來調用equals方法

7.整型包裝類對象之間值的比較必須使用equals方法

8.浮點數之間的等值判斷避免精度問題誤判


OOP規約指的是面向對象編程規範,英文全稱是 Object Oriented Programming面向對象程序設計是Java開發語言的一種計算機編程架構,它的基本原則是計算機程序是由單個能夠起到子程序作用的單元或對象組合而成

OOP 達到了軟件工程的三個主要目標:重用性靈活性擴展性。爲了實現整體運算,每個對象都能夠接收信息、處理數據和向其它對象發送信息。相對而言,開發中還有一種面向過程編程(POP,Procedure Oriented Programming)的思想,它是一種以過程爲中心的編程思想。該思想的開發過程就是分析出解決問題所需要的步驟,然後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就可以了。

作爲一種使用類和對象來設計程序的方法或模式,OOP提供一些概念簡化了軟件開發和維護:

  • 對象,任何具有狀態和行爲的實體都稱爲對象,例如:老師,學生,學校等。
  • 類,對象的集合稱爲類,它是一個邏輯實體。
  • 繼承,當一個對象獲取父對象的所有屬性和行爲時,稱爲繼承。它提供代碼可重用性,它用於實現運行時多態性。
  • 多態性,當一個任務通過不同的方式執行時,稱爲多態性,例如說話,人說人話,貓說話可以是:“喵喵”,而狗說話可能是“旺旺”等,說話時表示和聲音也不太一樣。
  • 抽象,隱藏內部細節和顯示功能稱爲抽象。例如:電話,但我們不知道內部是如何處理通話/通信的。
  • 封裝,將代碼和數據綁定(或包裝)在一起成爲單個單元稱爲封裝。例如:膠囊,它包裹着不同的藥物。
  • 組合,組合是聚合的特例。組合是一種更具限制性的聚合形式。例如,房子裏有房間。沒有房子,這裏的房間不可能存在。

本篇將針對上述概念對OOP規約問題進行總結,由於篇幅有限將分爲上中下三篇。

1.直接使用類名訪問靜態變量或靜態方法

Alibaba規約(強制

避免通過一個類的對象引用訪問此類的靜態變量或靜態方法,無謂增加編譯器解析成本,直接用類名來訪問即可。

Google規約

使用類名調用靜態的類成員,而不是具體某個對象或表達式。

說明:靜態成員的初始化和類的初始化一起完成,初始化後被放入方法區中,而且只會被初始化一次,不會因爲創建幾次對象而被多次初始化,因此爲節省內存空間建議直接通過類名調用,第一次通過類名調用靜態成員將觸發類的初始化,具體過程可以參考類的加載過程。

區別:兩個大廠表達的含義是一樣的。

正例:

// 獲取靜態變量的日期格式
SimpleDateFormat simpleDateFormat = DateFromatList.DATE_YYYY_MM_DD_HH_MM_SS;

// 訪問類 Person 的靜態方法獲取 count 值
Integer count = Person.getCount();

反例:

DateFromatList list = new DateFromatList();
SimpleDateFormat dateFormat = list.DATE_YYYY_MM_DD_HH_MM_SS;
        
Person person = new Person();
Integer number = person.getCount();

2.覆寫方法必須加@Override註解

Alibaba規約(強制

所有的覆寫方法,必須加 @Override 註解。

Google規約

只要是合法的,就把 @Override 註解給用上。

說明:子類重載父類的方法一般需要在方法前加上 @Override 註解,但是如果不添加編譯器也能識別且能正常運行,但是實際調用具體使用哪個方法可能存在問題。另一方面,getObject()與 get0bject()的問題。一個是字母的 O,一個是數字的 0,加@Override 可以準確判斷是否覆蓋成功。另外,如果在抽象類中對方法簽名進行修改,其實現類會馬上編譯報錯。

區別:無區別。

正例:

反例:

3.Java可變參數必須是相同參數和業務含義且避免使用Object類型

Alibaba規約(強制

相同參數類型,相同業務含義,纔可以使用Java的可變參數,避免使用Object。可變參數必須放置在參數列表的最後。(提倡同學們儘量不用可變參數編程)

Google規約

未明確定義類似規範

說明:Java 可變參數是1.5版本的新特性,也就是說用戶若是想定義一個方法,但是在此之前並不知道以後要用的時候想傳幾百個參數進去,可以在方法的參數列表中寫參數類型或度者數組名,然後在方法內部直接用操作數組的方式操作,具體案例可參考如下。

public class Demo {
    public static void main(String[] args) {
        System.out.println(getSum(1, 2, 3));
    }

    // 可變參數方法,array 即可變參數,調用時用逗號分隔可輸入多個參數
    public static int getSum(int... array) {
        int sum = 0;
        for (int i : array) {
            sum += i;
        }
        return sum;
    }
}

正例:

// ids可變參數爲多個相同業務邏輯的 id 參數
public List<User> listUsers(String type, Long... ids) {
    // 省略部分代碼
}

反例:

// 避免使用 Object 類型的可變參數
public List<User> listStudents(String type, Object... objects) {
    // 省略部分代碼
}

4.禁止修改調用或者二方庫依賴的接口方法簽名

Alibaba規約(強制

外部正在調用或者二方庫依賴的接口,不允許修改方法簽名,避免對接口調用方產生影響。接口過時必須加@Deprecated註解,並清晰地說明採用的新接口或者新服務是什麼。

Google規約

未明確定義類似規範

說明:規約中提到修改調用接口簽名可能導致調用方法出現問題,因此最好不要擅自修改。@Deprecated 註解添加後表示此方法或類不再建議使用,調用時也會出現刪除線,但並不代表不能用,只是說不推薦使用,因爲還有更好的方法可以調用。

5.禁止使用過時的類或方法

Alibaba規約(強制

不能使用過時的類或方法。

Google規約

未明確定義類似規範

說明:過時方法就是調用接口出現刪除線,開發過程應該避免此類問題。java.net.URLDecoder 中的方法decode(String encodeStr) 這個方法已經過時,應該使用雙參數decode(String source, String encode)。接口提供方既然明確是過時接口,那麼有義務同時提供新的接口;作爲調用方來說,有義務去考證過時方法的新實現是什麼。

反例:

補充:Spring的過時類,Spring5.0之前,攔截器配置都是直接繼承WebMvcConfigurerAdapter的,從5.0之後,這個類已廢棄,而5.0之後WebMvcConfigurer有了defalut方法,允許子類僅覆蓋那些需要的方法,所以這個適配器不需要了,直接繼承WebMvcConfigurer接口就可以。

6.使用常量或確定有值的對象來調用equals方法

Alibaba規約(強制

Object的equals方法容易拋空指針異常,應使用常量或確定有值的對象來調用equals。

Google規約

未明確定義類似規範

說明:新手經常犯的錯誤就是直接調用equals方法進行判斷,爲避免空指針異常必須執行該規則。推薦使用java.util.Objects#equals(JDK7引入的工具類)。

正例:

Person person = new Person();

if ("李四".equals(person.getName())){
    // 省去部分代碼
}


// 推薦使用 Objects.equals(Object a, Object b) 方法
String str1 = new String("123");
String str2 = new String("123");
        
boolean result = Objects.equals(str1, str2);

反例:

Person person = new Person();

if (person.getName().equals("李四")){
    // 省去部分代碼
}

7.整型包裝類對象之間值的比較必須使用equals方法

Alibaba規約(強制

所有整型包裝類對象之間值的比較,全部使用equals方法比較。

Google規約

未明確定義類似規範

說明:對於Integer var = ? 在-128至127範圍內的賦值,Integer對象是在 IntegerCache.cache產生,會複用已有對象,這個區間內的Integer值可以直接使用==進行判斷,但是這個區間之外的所有數據,都會在堆上產生,並不會複用已有對象,這是一個大坑,推薦使用equals方法進行判斷。

補充:Integer 和 Long 類型的自動裝箱的結果如下:

Integer x = 127;
Integer y = 127;
Integer m = 99999;
Integer n = 99999;
System.out.println("x == y: " + (x == y)); // true
System.out.println("m == n: " + (m == n)); // false
System.out.println("x.equals(y): " + x.equals(y)); // true
System.out.println("m.equals(n): " + m.equals(n)); // true

Long i = -128l;
Long j = -128l;
Long z = 9999l;
Long c = 9999l;
System.out.println("i == j: " + (i == j)); // true
System.out.println("z == c: " + (z == c)); // false
System.out.println("i.equals(j): " + i.equals(j)); // true
System.out.println("z.equals(c): " + z.equals(c)); // true

8.浮點數之間的等值判斷避免精度問題誤判

Alibaba規約(強制

浮點數之間的等值判斷,基本數據類型不能用==來比較,包裝數據類型不能用equals來判斷。

Google規約

未明確定義類似規範

說明:浮點數採用“尾數+階碼”的編碼方式,類似於科學計數法的“有效數字+指數”的表示方式。二進制無法精確表示大部分的十進制小數。

正例:

// 指定一個誤差範圍,兩個浮點數的差值在此範圍之內,則認爲是相等的。
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");
}

// 使用BigDecimal來定義值,再進行浮點數的運算操作。
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)) {
	System.out.println("true");
}

反例:

float a = 1.0f - 0.9f;
float b = 0.9f - 0.8f;
if (a == b) {
	// 預期進入此代碼快,執行其它業務邏輯
	// 但事實上a==b的結果爲false
}

Float x = Float.valueOf(a);
Float y = Float.valueOf(b);
if (x.equals(y)) {
	// 預期進入此代碼快,執行其它業務邏輯 
	// 但事實上equals的結果爲false 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章