乾貨!碼出高效,java代碼規範彙總

乾貨!碼出高效,java代碼規範彙總

點點贊 不迷路 文末領取博主精心爲大家準備的面試渡劫大禮包
在這裏插入圖片描述

作爲一名開發人員,當你接手他人的項目時,且當你閱讀他人的代碼時,是否急火攻心,暴跳如雷過,甚至有着大爆粗口的想法,此時的你看着那些密密麻麻的代碼就如同天書一般,羞澀難懂。反正我是有過,你們呢?

Robert Martin曾說過"在代碼閱讀中說髒話的頻率是衡量代碼質量額唯一標準"。當你發現別人看你的代碼時頻頻點頭,甚至投出欣賞的目光,那麼我想此時你的心情也會隨着他人一起愉悅,那種成就感對於程序員來說,是一種說不上的幸福!話不多說,直接乾貨!

本文完全採用阿里巴巴的java開發規範

如果您習慣用IDEA進行代碼開發,推薦一款實用的插件:Alibaba Java Coding Guidelines,可實時幫助我們檢測代碼規範!(本文重點在規範層面,具體用法且見下回分解)
在這裏插入圖片描述

頭一回檢測共發現 32+518+378=928處不規範的地方,甚是可怕!

1.避免用Apache Beanutils進行屬性的copy。

說明

Apache BeanUtils性能較差,可以使用其他方案比如Spring BeanUtils, Cglib BeanCopier。
    TestObject a = new TestObject();
    TestObject b = new TestObject();
    a.setX(b.getX());
    a.setY(b.getY());

注意點

  • 從Apache 的拷貝方案切換到Spring 的方案時,需要參數位置進行互換一下
  • Spring 的拷貝,需要保證拷貝與被拷貝的對象都擁有對應屬性的 getset 方法
  • 拷貝的兩個類必須擁有相同的成員變量
  • 如果兩個對象擁有2個屬性完全一致但是類名不同的內部類,會被認爲不是同一個類,不會執行拷貝
舉例:model類轉entity類
private String saveProjectMessage(ProjectModel projectModel) throws Exception{
        ProjectEntity projectEntity = new ProjectEntity();
        // org.apache.commons.beanutils.BeanUtils;
        BeanUtils.copyProperties(projectEntity,projectModel); // 摒棄
        org.springframework.beans.BeanUtils.copyProperties(projectModel,projectEntity); //推薦
        return commonProjectBiz.saveProject(projectEntity);
    }

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

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

Integer a = 235;
Integer b = 235;
if (a.equals(b)) {
    // code
}

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

反例
public void f(String str){
        if (str.equals("hi")) {
            System.out.println("hello world");
        }
    }

public void f(String str){
        String inner = "hi";
        if (inner.equals(str)) {
            System.out.println("hello world");
        }
    }

4.集合初始化時,指定集合初始值大小。

說明

HashMap使用如下構造方法進行初始化,如果暫時無法確定集合大小,那麼指定默認值(16)即可。

反例:   
   Map<String, String> map = new HashMap<String, String>();
正例: 
   Map<String, String> map = new HashMap<String, String>(16);

5.除常用方法(如getXxx/isXxx)等外,不要在條件判斷中執行復雜的語句,將複雜邏輯判斷的結果賦值給一個有意義的布爾變量,以提高可讀性。

說明

很多if語句內的邏輯相當複雜,閱讀者需要分析條件表達式的最終結果,才能明確什麼樣的條件執行什麼樣的語句,那麼,如果閱讀者分析邏輯表達式錯誤呢?

反例

if ((file.open(fileName, "w") != null) && (...) || (...)) {
        // ...
    }

正例

boolean existed = (file.open(fileName, "w") != null) && (...) || (...);
    if (existed) {
        //...
    }

6.不允許任何魔法值(即未經定義的常量)直接出現在代碼中

反例

if (key.equals("Id#taobao_1")) {
            //...
    }

正例

 String KEY_PRE = "Id#taobao_1";
    if (KEY_PRE.equals(key)) {
            //...
    }

7.Map/Set的key爲自定義對象時,必須重寫hashCode和equals

說明

關於hashCode和equals的處理,遵循如下規則:
1.只要重寫equals,就必須重寫hashCode 
2.因爲Set存儲的是不重複的對象,依據hashCode和equals進行判斷,所以Set存儲的對象必須重寫這兩個方法 
3.如果自定義對象做爲Map的鍵,那麼必須重寫hashCode和equals。 

舉例

// 定義一個車牌類
public class CarNumber {
    private String cityCode; // 城市代號
    private String number; // 車牌號

    public String getCityCode() {
        return cityCode;
    }

    public void setCityCode(String cityCode) {
        this.cityCode = cityCode;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

反例

public class Test {
    public static void main(String [] args) {

        //  key爲自定義類
        Map<CarNumber, String> map =new HashMap<>(16);

        CarNumber car1 = new CarNumber();
        car1.setCityCode("蘇A");
        car1.setNumber("11111");
        CarNumber car2 = new CarNumber();
        car2.setCityCode("蘇A");
        car2.setNumber("22222");

        map.put(car1, "車牌號1");
        map.put(car2, "車牌號2");

        // 參數內容和car2對象一樣
        CarNumber car3 = new CarNumber();
        car3.setCityCode("蘇A");
        car3.setNumber("22222");
        
        //控制檯輸出
        System.out.println(map.get(car1));
        System.out.println(map.get(car2));
        System.out.println(map.get(car3));
    }
}

輸出結果爲:

在這裏插入圖片描述

正常理解car2&car3對象從hashMap中取值應該是相同的,但如果不重寫hashcode()方法,比較是其地址,car3和car2地址不同,所以不相等!

正例

public class CarNumber {
    private String cityCode; // 城市代號
    private String number; // 車牌號

    //在CarNumber 類中重寫equals()和hashCode()方法;
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CarNumber carNumber = (CarNumber) o;
        return Objects.equals(cityCode, carNumber.cityCode) &&
                Objects.equals(number, carNumber.number);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(cityCode, number);
    }
}

輸出結果爲

在這裏插入圖片描述

原理

  • HashMap中的比較key是這樣的,先求出key的hashcode(),比較其值是否相等,若相等再比較equals(),若相等則認爲他們是相等 的。若equals()不相等則認爲他們不相等。
  • 如果只重寫hashcode()不重寫equals()方法,當比較equals()時只是看他們是否爲同一對象(即進行內存地址的比較),所以必定要兩個方法一起重寫。
  • HashMap用來判斷key是否相等的方法,其實是調用了HashSet判斷加入元素 是否相等。

8.對於Service和DAO類,基於SOA的理念,暴露出來的服務一定是接口,內部的實現類用Impl的後綴與接口區別

反例

public interface DemoService{
        void f();
}

正例

public class DemoServiceImpl implements DemoService {
     @Override
     public void f(){
         System.out.println("hello world");
     }
}

9.單個方法的總行數不超過80行

說明

除註釋之外的方法簽名、結束右大括號、方法內代碼、空行、回車及任何不可見字符的總行數不超過80行。

10.方法內部單行註釋,在被註釋語句上方另起一行,使用//註釋。方法內部多行註釋使用/* */註釋。注意與代碼對齊。

public void method() {
        // Put single line comment above code. (Note: align '//' comment with code)
        int a = 3;
    
        /**
        * Some description about follow code. (Note: align '/**' comment with code)
        */
        int b = 4;
}


11.所有編程相關的命名均不能以下劃線或美元符號開始

反例

private void $test(){
    System.out.println("命名不能以美元符號開始")
}

private void _test(){
    System.out.println("命名不能以下劃線開始")
}

12.所有的抽象方法(包括接口中的方法)必須要用javadoc註釋、除了返回值、參數、異常說明外,還必須指出該方法做什麼事情,實現什麼功能。

說明:如有實現和調用注意事項,請一併說明。

正例

/**
* fetch data by rule id
* 
* @param ruleId 規則Id
* @param page 頁數
* @param jsonContext json字符串
* @return Result<XxxxDO> 出參
*/
Result<XxxxDO> fetchDataByRuleId(Long ruleId, Integer page, String jsonContext);

13.方法名、參數名、成員變量、局部變量都統一使用lowerCamelCase,必須遵從駝峯形式

反例

void selectTODOList(Map<String,Object> todoMap);

正例

void selectTODOList(Map<String,Object> todoMap);

14.包名統一使用小寫,點分隔符之間有且僅有一個自然語義的英語單詞。包名統一使用單數形式,但是類名如果有複數含義,類名可以使用複數形式

正例

com.alibaba.mpp.util / com.taobao.tddl.domain.dto

15.不能使用過時的類或方法

說明

java.net.URLDecoder 中的方法decode(String encodeStr)這個方法已經過時

應該使用雙參數decode(String source, String encode)

接口提供方既然明確是過時接口,那麼有義務同時提供新的接口;作爲調用方來說,有義務去考證過時方法的新實現是什麼。

16.常量命名應該全部大寫,單詞間用下劃線隔開,力求語義表達完整清楚,不要嫌名字長


17.所有的覆寫方法,必須加@Override註解、

反例

getObject()get0bject()的問題。

一個是字母的O,一個是數字的0,加@Override可以準確判斷是否覆蓋成功。

另外,如果在抽象類中對方法簽名進行修改,其實現類會馬上編譯報錯。

18.在if/else/for/while/do語句中必須使用大括號,即使只有一行代碼,避免使用下面的形式:if (condition) statements;

反例

if(flag) System.out.println("hello world");

正例

if (flag) {
   System.out.println("hello world");
}

19.常量命名應該全部大寫,單詞間用下劃線隔開,力求語義表達完整清楚,不要嫌名字長

public class ConstantNameDemo {

    /**
    * max stock count
    */
    public static final Long MAX_STOCK_COUNT = 50000L;

20.所有的枚舉類型字段必須要有註釋,說明每個數據項的用途。

正例

public enum TestEnum {
        /**
         * agree
         */
        agree("agree"),
        /**
         * reject
         */
        reject("reject");
        
        private String action;
    
        TestEnum(String action) {
            this.action = action;
        }
    
        public String getAction() {
            return action;
        }
    }

21.所有的類都必須添加創建者信息。

說明

在設置模板時,注意IDEA的@author爲${USER},
而eclipse的@author爲${user},大小寫有區別,而日期的設置統一爲yyyy/MM/dd的格式。

正例

/**
     * Demo class
     * 
     * @author java醬
     * @date 2020/01/10
     */
    public class CodeNoteDemo {
    }

結語

好了,本文到這裏節結束啦,希望對大家有所幫助,如果有任何疑問,歡迎評論區留言
最後 : 小編在這裏給大家分享一份 2019年多家公司java面試題整理120多頁pdf文檔的PDF,希望大家在之後的面試中和技術提升能夠事半功倍,需要的朋友們點贊評論喔~

羣號:530720915 點擊加入 進羣驗證“csdn” 獲取
在這裏插入圖片描述

最後
歡迎大家一起交流,整理資料不易,喜歡文章記得點個讚唄,感謝支持!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章