《阿里巴巴Java規(guī)約插件》使用總結(jié)

前言

小編用自己的項目做白老鼠琴昆,試試這個阿里巴巴榮譽出品的《Java規(guī)約插件》


結(jié)果居然有4800+條問題7掀瘛!簡直嚇得小編懷疑人生有木有1即?(默哀0.01秒)小編依舊懷著認(rèn)真的科學(xué)精神進(jìn)入試驗田(快開車,別廢話!)悦陋。如想了解如何安裝插件和插件的使用技巧請猛戳:http://www.reibang.com/p/834899aa90b4

入題

掃描出三個分類結(jié)果(類jira的bug優(yōu)先級分為:blocker,critical,major,minor,trivial)

  • Blocker 有妨礙的
  • Critical 緊要的
  • Major 嚴(yán)重的

具體的語法問題,值得學(xué)習(xí)下:

Blocker 有妨礙的
  • 在if/else/for/while/do語句中必須使用大括號筑辨,即使只有一行代碼俺驶,避免使用下面的形式:if (condition) statements;

  • 在使用正則表達(dá)式時,利用好其預(yù)編譯功能棍辕,可以有效加快正則匹配速度暮现。
    說明:不要在方法體內(nèi)定義:Pattern pattern = Pattern.compile(規(guī)則);
    public class XxxClass {
    // Use precompile
    private static Pattern NUMBER_PATTERN = Pattern.compile("[0-9]+");
    public Pattern getNumberPattern() {
    // Avoid use Pattern.compile in method body.
    Pattern localPattern = Pattern.compile("[0-9]+");
    return localPattern;
    }
    }

  • 多線程并行處理定時任務(wù)時,Timer運行多個TimeTask時楚昭,只要其中之一沒有捕獲拋出的異常栖袋,其它任務(wù)便會自動終止運行,使用ScheduledExecutorService則沒有這個問題抚太。 //org.apache.commons.lang3.concurrent.BasicThreadFactory
    ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
    new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());
    executorService.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
    //do something
    }
    },initialDelay,period, TimeUnit.HOURS);

  • 所有的覆寫方法塘幅,必須加@Override注解。 反例:getObject()與get0bject()的問題尿贫。一個是字母的O电媳,一個是數(shù)字的0,加@Override可以準(zhǔn)確判斷是否覆蓋成功庆亡。另外匾乓,如果在抽象類中對方法簽名進(jìn)行修改,其實現(xiàn)類會馬上編譯報錯又谋。

  • 線程池不允許使用Executors去創(chuàng)建拼缝,而是通過ThreadPoolExecutor的方式,這樣的處理方式讓寫的同學(xué)更加明確線程池的運行規(guī)則彰亥,規(guī)避資源耗盡的風(fēng)險咧七。 說明:Executors各個方法的弊端:
    1)newFixedThreadPool和newSingleThreadExecutor:
    ??主要問題是堆積的請求處理隊列可能會耗費非常大的內(nèi)存,甚至OOM剩愧。
    2)newCachedThreadPool和newScheduledThreadPool:
    ??主要問題是線程數(shù)最大數(shù)是Integer.MAX_VALUE猪叙,可能會創(chuàng)建數(shù)量非常多的線程娇斩,甚至OOM仁卷。

Positive example 1:
//org.apache.commons.lang3.concurrent.BasicThreadFactory
ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,
new BasicThreadFactory.Builder().namingPattern("example-schedule-pool-%d").daemon(true).build());

Positive example 2:
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("demo-pool-%d").build();

//Common Thread Pool
ExecutorService pool = new ThreadPoolExecutor(5, 200,
     0L, TimeUnit.MILLISECONDS,
     new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

pool.execute(()-> System.out.println(Thread.currentThread().getName()));
pool.shutdown();//gracefully shutdown

Positive example 3:
<bean id="userThreadPool"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="10" />
<property name="maxPoolSize" value="100" />
<property name="queueCapacity" value="2000" />

<property name="threadFactory" value= threadFactory />
    <property name="rejectedExecutionHandler">
        <ref local="rejectedExecutionHandler" />
    </property>
</bean>
//in code
userThreadPool.execute(thread);
  • 避免通過一個類的對象引用訪問此類的靜態(tài)變量或靜態(tài)方法穴翩,無謂增加編譯器解析成本,直接用類名來訪問即可锦积。

  • Critical 緊要的

Object的equals方法容易拋空指針異常芒帕,應(yīng)使用常量或確定有值的對象來調(diào)用equals。

public void f(String str){
    String inner = "hi";
    if(inner.equals(str)){
        System.out.println("hello world");
    }
}
  • SimpleDateFormat 是線程不安全的類丰介,一般不要定義為static變量背蟆,如果定義為static,必須加鎖哮幢,或者使用DateUtils工具類带膀。 說明:如果是JDK8的應(yīng)用,可以使用instant代替Date橙垢,LocalDateTime代替Calendar垛叨,DateTimeFormatter代替SimpleDateFormat,官方給出的解釋:simple beautiful strong immutable thread-safe柜某。

Positive example 1:
private static final String FORMAT = "yyyy-MM-dd HH:mm:ss";
public String getFormat(Date date){
SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT);
return sdf.format(date);
}

Positive example 2:
private static final SimpleDateFormat SIMPLE_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void getFormat(){
synchronized (sdf){
sdf.format(new Date());
….;
}

Positive example 3:
private static final ThreadLocal<DateFormat> DATE_FORMATTER = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};

  • 不能使用過時的類或方法嗽元。 說明:java.net.URLDecoder 中的方法decode(String encodeStr) 這個方法已經(jīng)過時,應(yīng)該使用雙參數(shù)decode(String source, String encode)喂击。接口提供方既然明確是過時接口剂癌,那么有義務(wù)同時提供新的接口;作為調(diào)用方來說翰绊,有義務(wù)去考證過時方法的新實現(xiàn)是什么佩谷。

  • 在一個switch塊內(nèi),每個case要么通過break/return等來終止监嗜,要么注釋說明程序?qū)⒗^續(xù)執(zhí)行到哪一個case為止琳要;在一個switch塊內(nèi),都必須包含一個default語句并且放在最后秤茅,即使它什么代碼也沒有稚补。

    switch( x ){
    case 1 :
    break ;
    case 2 :
    break ;
    default :
    }

  • 常量命名應(yīng)該全部大寫,單詞間用下劃線隔開框喳,力求語義表達(dá)完整清楚课幕,不要嫌名字長

    public class ConstantNameDemo {

    /**

    • max stock count
      */
      public static final Long MAX_STOCK_COUNT = 50000L;
  • 所有的枚舉類型字段必須要有注釋,說明每個數(shù)據(jù)項的用途五垮。
    public enum TestEnum {
    /**
    * agree
    /
    agree("agree"),
    /
    *
    * reject
    */
    reject("reject");

      private String action;
    
      TestEnum(String action) {
          this.action = action;
      }
    
      public String getAction() {
          return action;
      }
    

    }

  • 所有編程相關(guān)的命名均不能以下劃線或美元符號開始

  • 抽象類命名使用Abstract或Base開頭

    abstract class BaseControllerDemo{
    }

    abstract class AbstractActionDemo{
    }

  • 方法名乍惊、參數(shù)名、成員變量放仗、局部變量都統(tǒng)一使用lowerCamelCase润绎,必須遵從駝峰形式

  • Major 嚴(yán)重的
  • 不允許任何魔法值(即未經(jīng)定義的常量)直接出現(xiàn)在代碼中。
    Negative example:
    //Magic values, except for predefined, are forbidden in coding.
    if(key.equals("Id#taobao_1")){
    //...
    }
    Positive example:
    String KEY_PRE = "Id#taobao_1";
    if(key.equals(KEY_PRE)){
    //...
    }

  • 中括號是數(shù)組類型的一部分,數(shù)組定義如下:String[] args

    String[] a = new String[3];

  • 及時清理不再使用的代碼段或配置信息莉撇。 說明:對于垃圾代碼或過時配置呢蛤,堅決清理干凈,避免程序過度臃腫棍郎,代碼冗余其障。
    Positive example: For codes which are temporarily removed and likely to be reused, use /// to add a reasonable note.
    public static void hello() {
    /// Business is stopped temporarily by the owner.
    // Business business = new Business();
    // business.active();
    System.out.println("it's finished");
    }

  • 循環(huán)體內(nèi),字符串的聯(lián)接方式涂佃,使用StringBuilder的append方法進(jìn)行擴展励翼。 說明:反編譯出的字節(jié)碼文件顯示每次循環(huán)都會new出一個StringBuilder對象,然后進(jìn)行append操作辜荠,最后通過toString方法返回String對象汽抚,造成內(nèi)存資源浪費。
    反例:
    String result;
    for (String string : tagNameList) {
    result = result + string;
    }
    正例:
    StringBuilder stringBuilder = new StringBuilder();
    for (String string : tagNameList) {
    stringBuilder.append(string);
    }
    String result = stringBuilder.toString();

  • 所有的抽象方法(包括接口中的方法)必須要用javadoc注釋伯病、除了返回值殊橙、參數(shù)、異常說明外狱从,還必須指出該方法做什么事情膨蛮,實現(xiàn)什么功能。 說明:如有實現(xiàn)和調(diào)用注意事項季研,請一并說明敞葛。
    /**

    • fetch data by rule id
    • @param ruleId rule id
    • @param page page number
    • @param jsonContext json format context
    • @return Result<XxxxDO>
      */
      Result<XxxxDO> fetchDataByRuleId(Long ruleId, Integer page, String jsonContext);
  • 所有的類都必須添加創(chuàng)建者信息。 說明:在設(shè)置模板時与涡,注意IDEA的@author為${USER}惹谐,而eclipse的@author為${user},大小寫有區(qū)別驼卖,而日期的設(shè)置統(tǒng)一為yyyy/MM/dd的格式氨肌。
    /**

    • Demo class
    • @author keriezhang
    • @date 2016/10/31
      */
      public class CodeNoteDemo {
      }
  • 方法內(nèi)部單行注釋,在被注釋語句上方另起一行酌畜,使用//注釋怎囚。方法內(nèi)部多行注釋使用/* */注釋。注意與代碼對齊桥胞。
    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;
    

    }

  • 類恳守、類屬性、類方法的注釋必須使用javadoc規(guī)范贩虾,使用/內(nèi)容/格式催烘,不得使用//xxx方式和/xxx/方式。 說明:在IDE編輯窗口中缎罢,javadoc方式會提示相關(guān)注釋伊群,生成javadoc可以正確輸出相應(yīng)注釋考杉;在IDE中,工程調(diào)用方法時舰始,不進(jìn)入方法即可懸浮提示方法崇棠、參數(shù)、返回值的意義蔽午,提高閱讀效率易茬。
    /
    *

    • XXX class function description.

    /
    public class XxClass implements Serializable {
    private static final long serialVersionUID = 113323427779853001L;
    /
    *
    * id
    /
    private Long id;
    /
    *
    * title
    */
    private String title;

      /**
       * find by id
       * 
       * @param ruleId rule id
       * @param page start from 1
       * @return Result<Xxxx>
       */
      public Result<Xxxx> funcA(Long ruleId, Integer page) {
          return null;
      }
    

    }

  • 類名使用UpperCamelCase風(fēng)格酬蹋,必須遵從駝峰形式及老,但以下情形例外:(領(lǐng)域模型的相關(guān)命名)DO / BO / DTO / VO / DAO

  • 除常用方法(如getXxx/isXxx)等外,不要在條件判斷中執(zhí)行復(fù)雜的語句范抓,將復(fù)雜邏輯判斷的結(jié)果賦值給一個有意義的布爾變量骄恶,以提高可讀性。 說明:很多if語句內(nèi)的邏輯相當(dāng)復(fù)雜匕垫,閱讀者需要分析條件表達(dá)式的最終結(jié)果僧鲁,才能明確什么樣的條件執(zhí)行什么樣的語句,那么象泵,如果閱讀者分析邏輯表達(dá)式錯誤呢寞秃?

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

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

  • 集合初始化時,指定集合初始值大小偶惠。 說明:HashMap使用如下構(gòu)造方法進(jìn)行初始化春寿,如果暫時無法確定集合大小,那么指定默認(rèn)值(16)即可忽孽。

Negative example:
Map<String, String> map = new HashMap<String, String>();

Positive example:
Map<String, String> map = new HashMap<String, String>(16);

小結(jié)

總的來說绑改,阿里巴巴Java規(guī)約插件還是對項目很有幫助的,大家用起來吧兄一。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末厘线,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子出革,更是在濱河造成了極大的恐慌造壮,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骂束,死亡現(xiàn)場離奇詭異费薄,居然都是意外死亡,警方通過查閱死者的電腦和手機栖雾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門楞抡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人析藕,你說我怎么就攤上這事召廷。” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵竞慢,是天一觀的道長先紫。 經(jīng)常有香客問我,道長筹煮,這世上最難降的妖魔是什么遮精? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮败潦,結(jié)果婚禮上本冲,老公的妹妹穿的比我還像新娘。我一直安慰自己劫扒,他們只是感情好檬洞,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著沟饥,像睡著了一般添怔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贤旷,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天广料,我揣著相機與錄音,去河邊找鬼幼驶。 笑死艾杏,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的县遣。 我是一名探鬼主播糜颠,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼萧求!你這毒婦竟也來了其兴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤夸政,失蹤者是張志新(化名)和其女友劉穎元旬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體守问,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡匀归,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了耗帕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片穆端。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖仿便,靈堂內(nèi)的尸體忽然破棺而出体啰,到底是詐尸還是另有隱情攒巍,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布荒勇,位于F島的核電站柒莉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏沽翔。R本人自食惡果不足惜兢孝,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仅偎。 院中可真熱鬧跨蟹,春花似錦、人聲如沸哨颂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽威恼。三九已至,卻和暖如春寝并,著一層夾襖步出監(jiān)牢的瞬間箫措,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工衬潦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留斤蔓,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓镀岛,卻偏偏與公主長得像弦牡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子漂羊,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容