CheckStyle檢查規則中文翻譯

本文主要介紹CheckStyle 的各個規則配置項目,這個版本的CheckStyle將樣式規則分爲了如下十六種類型共138條規則:html

官方文檔地址:http://checkstyle.sourceforge.net/index.htmljava

1. Annotations(註解:7個)

  • AnnotationLocation(註解使用位置)

這項檢查能夠控制要使用的註解的位置。程序員

  • AnnotationUseStyle(註解使用風格)

這項檢查能夠控制要使用的註解的樣式。正則表達式

  • MissingDeprecated(缺乏deprecad

檢查java.lang.Deprecated註解或@deprecated的Javadoc標記是否同時存在。算法

  • MissingOverride(缺乏override

當出現{@inheritDoc}的Javadoc標籤時,驗證java.lang.Override註解是否出現。編程

  • PackageAnnotation(包註解)

這項檢查能夠確保全部包的註解都在package-info.java文件中。數組

  • SuppressWarnings(抑制警告)

這項檢查容許你指定不容許SuppressWarnings抑制哪些警告信息。你還能夠指定一個TokenTypes列表,其中包含了全部不能被抑制的警告信息。緩存

  • SuppressWarningsHolder(//TODO...)

//這項檢查。安全

 

2. Block Checks(代碼塊:6個)

  • AvoidNestedBlocks(避免嵌套代碼塊)

找到嵌套代碼塊,也就是在代碼中無節制使用的代碼塊。數據結構

解釋:內嵌代碼塊一般是調試過程的殘留物,它們會使讀者產生混淆。

  • EmptyBlock(空代碼塊)

檢查空代碼塊。

  • EmptyCatchBlock//TODO...

//TODO...

  • LeftCurly(左花括號位置)

檢查代碼塊的左花括號的放置位置。

經過property選項指定驗證策略。

若使用eol和nlow策略,則須要考慮maxLineLength屬性。

  • NeedBraces(須要花括號)

檢查代碼塊周圍是否有大括號,能夠檢查do、else、if、for、while等關鍵字所控制的代碼塊。

  • RightCurly(右花括號位置)

檢查else、try、catch標記的代碼塊的右花括號的放置位置。

經過property選項指定驗證策略。

 

3. Class Design(類設計:9個)

  • DesignedForExtension(設計擴展性)

檢查類是否具備可擴展性。更準確地說,它強制使用一種編程風格,父類必須提供空的「句柄」,以便於子類實現它們。
確切的規則是,類中能夠由子類繼承的非私有、非靜態方法必須是:
1. abstract方法,或

2. final方法,或

3. 有一個空的實現

解釋:這種API設計風格能夠保護父類不會被子類破壞。不利之處在於子類的靈活性會受到限制,特別是它們不可以阻止父類代碼的執行,可是這也意味着子類不會因爲忘記調用父類的方法而破壞父類的狀態。(我的理解:不容許類的方法被子類覆蓋)

  • FinalClassfinal類)

檢查一個只有私有構造器的類是否被聲明爲final。

  • HideUtilityClassConstructor(隱藏工具類構造器)

確保工具類(在API中只有靜態方法和字段的類)沒有任何公有構造器。

解釋:實例化工具類沒有任何意義。所以,工具類的構造器應當是私有的或者受保護的(若是你打算之後擴展子類)。一個常見的錯誤即是忘記隱藏默認構造器。

若是你打算將工具類的構造器聲明爲受保護的,那麼你能夠考慮下面的構造器實現技術,藉此能夠禁止子類的實例化:
public class StringUtils // 不是final類,容許子類繼承
{
    protected StringUtils() {
        throw new UnsupportedOperationException(); // 防止子類調用
    }

    public static int count(char c, String s) {
        // ...
    }
}

  • InnerTypeLast(最後聲明內部類型)

檢查嵌套/內部的類型是否在當前類的最底部聲明(在全部的方法/字段的聲明以後)。

  • InterfaceIsType(接口是類型)

Bloch編寫的《Effective Java》中提到,接口應當描述爲一個類型。所以,定義一個只包含常量,可是沒有包含任何方法的接口是不合適的。標準類javax.swing.SwingConstants是一個會被這項檢查標記的示例類。


這項檢查還能夠配置爲禁用標記接口,例如java.io.Serializable,這種接口不會包含任何方法或常量。

  • MutableException(可變異常)

確保異常(異常類的名稱必須匹配指定的正則表達式)是不可變的。也就是說,異常只能有final字段。

這項檢查當前使用的算法很是簡單,它會檢查異常的全部成員是不是final的。用戶仍然能夠修改一個異常實例(例如,Throwable使用setStackTrace(StackTraceElement[] stackTrace)方法修改堆棧跟蹤)。可是,至少這種異常類型所提供的信息是不可修改的。
解釋:異常實例應當表示一個錯誤狀態。異常類中含有非final的字段,不只僅會致使異常狀態會因爲偶然的因素被修改,這樣便會遮蔽原始的異常狀態,還會使得開發者偶爾會忘記初始化異常狀態,這樣便會致使代碼捕捉到異常以後,根據異常狀態推導出不正確的結論。

  • OneTopLevelClass//TODO

//TODO...


這項檢查還能夠配置爲禁用標記接口,例如java.io.Serializable,這種接口不會包含任何方法或常量。

  • ThrowsCount(拋出計數)

將異常拋出語句的數量配置爲一個指定的限值(默認值爲1)。

解釋:異常是方法接口的組成部分之一。若是一個方法聲明拋出過多不一樣的異常,就會使得異常處理很是繁重,而且會致使很差的編程習慣,例如catch (Exception)。這項檢查會強制開發者將異常處理變得具備層次性,舉個最簡單的例子,調用者只須要檢查一種類型的異常,可是必要時也容許捕捉上述異常的任何子類。

  • VisibilityModifier(可見性標識符)

檢查類成員的可見性。只有static final的類成員能夠是公有的,其餘的類成員必須是私有的,除非設置了protectedAllowed屬性或packageAllowed屬性。

若是類成員的名稱和指定的公有成員正則表達式匹配,那麼這項檢查就不會標記這個類成員(默認包含「^serialVersionUID$」)。
解釋:強制封裝。

 

4. Coding(編碼問題:43個)

  • ArrayTrailingComma//TODO...

//TODO...

  • AvoidInlineConditionals(避免內聯條件語句)

檢測內聯條件語句。內聯條件語句的一個示例以下所示:
String a = getParameter("a");
String b = (a==null || a.length<1) ? null : a.substring(1);

解釋:有些開發者發現內聯條件語句很難讀懂,所以他們公司的編碼標準會禁止使用內聯條件語句。

  • CovariantEquals(共變equals方法)

檢查定義了共變equals()方法的類中是否一樣覆蓋了equals(java.lang.Object)方法。這項檢查受到FindBugs的啓發。

解釋:錯誤地定義了一個共變equals()方法,而沒有覆蓋equals(java.lang.Object)方法,可能會產生不可預料的運行時行爲。

  • DeclarationOrderCheck(聲明順序檢查)

根據Java編程語言的編碼規約,一個類或接口的聲明部分應當按照如下順序出現:

1. 類(靜態)變量。首先應當是public類變量,而後是protected類變量,而後是package類變量(沒有訪問標識符),最後是private類變量。

2. 實例變量。首先應當是public類變量,而後是protected類變量,而後是package類變量(沒有訪問標識符),最後是private類變量。

3. 構造器

4. 方法

  • DefaultComesLast(默認分支置於最後)

檢查switch語句中的default是否在全部的case分支以後。

解釋:Java容許default位於switch語句中的任何地方。可是,若是default位於最後一個case分支以後,那麼代碼的可讀性會更強。

  • EmptyStatement(空語句)

檢測代碼中是否有空語句(也就是單獨的;符號)。

  • EqualsAvoidNull(避免調用空引用的equals方法)

檢查equals()比較方法中,任意組合的String常量是否位於左邊。

這項檢查還會處理String.equalsIgnoreCase()調用(能夠抑制這種警告)。


解釋:調用String常量的equals()方法能夠避免潛在的NullPointerException。一樣,常常會發如今調用equals()方法以前,會進行空指針檢查,不過在下面的示例中則沒有必要這麼作。

例如:
String nullString = null;
nullString.equals("My_Sweet_String");    

這段代碼應當重構爲:     
String nullString = null;
"My_Sweet_String".equals(nullString);


侷限:若是覆蓋了equals方法,或者定義了一個共變equals方法,而且沒有正確地實現這個方法(也就是s.equals(t)返回的結果和t.equals(s)返回的結果不一樣),那麼改寫調用方法的對象和參數可能會產生沒法預料的結果。

Java的Autoboxing特性會對這項檢查如何實現產生影響。在Java 5以前的版本,全部的IDENT + IDENT對象拼接不會致使NullPointerException,即便它是空指針。這項檢查已經包含了這些狀況。它們會進行簡單的處理,就好像使用String.valueof()方法包圍起來同樣,這個方法會拼接null字符串。

如下示例將會致使一個NullPointerException,這是Autoboxing功能所形成的結果:
Integer i = null, j = null;
String number = "5"
number.equals(i + j);
由於很難肯定正在拼接的是哪一種類型的對象,因此全部的IDENT拼接都會被認爲是不安全的。

  • EqualsandHashCodeequals方法和hashCode方法)

檢查覆蓋了equals()方法的類是否也覆蓋了hashCode()方法。

解釋:equals()方法和hashCode()方法約定,相等的對象必然具備相同的哈希碼。所以,只要你覆蓋了equals()方法,你就必須同時覆蓋hashCode()方法,以確保能夠在基於哈希的集合中使用你的類。

  • ExplicitInitialization(顯式初始化)

檢查類或對象的成員是否顯式地初始化爲成員所屬類型的默認值(對象引用的默認值爲null,數值和字符類型的默認值爲0,布爾類型的默認值爲false)。

解釋:每一個實例變量都會被初始化兩次,而且初始化爲相同的值。在執行代碼中指定的任何初始化操做以前,Java會初始化每一個實例變量爲它的默認值(0或null)。所以在這種狀況下,x會被初始化爲0兩次,bar會被初始化爲null兩次。所以,這樣稍微有些效率低下。這種編碼風格是C/C++編碼風格的延續,它代表開發者並非真正有把握Java可以初始化實例變量爲它的默認值。

  • FallThrough(跨越分支)

檢查switch語句中是否存在跨越分支。若是一個case分支的代碼中缺乏break、return、throw或continue語句,那麼就會致使跨越分支。
這項檢查能夠經過特殊的註釋以抑制警告。默認狀況下,在有跨越分支的case分支代碼中添加「fallthru」、「fall through」、「fallthrough」、「falls through」、「fallsthrough」等註釋(區分大小寫)時,即可抑制警告。包含以上單詞的註釋必須在一行中,而且必須在當前case分支代碼的最後一行中,或者與case語句在同一行,如如下代碼所示:

switch (i){
case 0:
    i++; // fall through

case 1:
    i++;
    // falls through
case 2: {
    i++;
}
// fallthrough
case 3:
    i++;
/* fallthru */case 4:
    i++
    break;
}

注意:這項檢查假設case分支代碼中沒有不可達的代碼。

  • FinalLocalVariablefinal局部變量)

檢查從未改變取值的局部變量是否被聲明爲final。這項檢查還能夠被配置爲檢查未修改過的參數是否被聲明爲final。

當配置爲檢查參數時,這項檢查會忽略接口方法和抽象方法中的參數。

  • HiddenField(隱藏字段)

檢查局部變量或參數是否會遮蔽在相同類中定義的字段。

  • IllegalCatch(非法異常捕捉)

從不容許捕捉java.lang.Exception、java.lang.Error、java.lang.RuntimeException的行爲。

解釋:缺少經驗的開發者常常會簡單地捕捉Exception異常,試圖處理多種異常類型。這會很不幸地使代碼無心中捕捉到NullPointerException、OutOfMemoryErrors等系統異常。

  • IllegalInstantiation(非法實例化)

檢查是否有不合法的實例化操做,是否使用工廠方法更好。

解釋:根據不一樣的項目,對於某些類來講,可能經過工廠方法來建立類實例更好,而不是調用類構造器。
一個簡單的示例就是java.lang.Boolean類。爲了節省內存和CPU週期,最好使用預約義的常量TRUE和FALSE。構造器的調用應當被替換爲調用Boolean.valueOf()方法。

某些對性能有極端要求的項目可能須要其餘的類也使用工廠方法,以便於提升緩存或對象池的使用效率。

  • IllegalThrows(非法異常拋出)

這項檢查能夠用來確保類型不能聲明拋出指定的異常類型。從不容許聲明拋出java.lang.Error或java.lang.RuntimeException。

  • IllegalTokens(非法標記)

檢查不合法的標記。

解釋:某個語言特性常常會致使代碼難以維護,或者開發新手難以理解。在某些框架中,其餘特性可能不推薦使用,例如,在EJB組件中最好不要使用本地方法。

  • IllegalTokensText(非法標記文本)

檢查是否有不合法的標記文本。

  • IllegalType(非法類型)

檢查代碼中是否有在變量聲明、返回值、參數中都沒有做爲類型使用過的特定類。包括一種格式檢查功能,默認狀況下不容許抽象類。

解釋:幫助減小和實體類之間的耦合。另外,抽象類應當被認爲是接口的一種簡便的基類實現,所以不能是類型自己。

  • InnerAssignment(內部賦值)

檢查子表達式中是否有賦值語句,例如String s = Integer.toString(i = 2);。

解釋:這項檢查會忽略for循環代碼,其他全部的賦值操做都應當在它們本身的頂層語句中,以便於加強可讀性。在上述的內部賦值代碼中,很難看到變量是在哪兒賦值的。

  • MagicNumber(幻數)

檢查代碼中是否含有「幻數」,幻數就是沒有被定義爲常量的數值文字。默認狀況下,-一、0、一、2不會被認爲是幻數。

  • MissingConstructor(缺乏構造器)

檢查類(除了抽象類)是否認義了一個構造器,而不是依賴於默認構造器。

  • MissingSwitchDefault(缺乏switch默認分支)

檢查switch語句是否含有default子句。

解釋:在每一個switch語句中引入一條默認分支一般是一個很好的主意。即便開發者確信全部當前可能的分支都能覆蓋到,這也應當在default分支中表達出來,例如,使用一條斷言。這種方法使得代碼能夠應付之後的修改,例如,在一個枚舉類型中引入新的類型。

  • ModifiedControlVariable(修改控制變量)

檢查確保for循環的控制變量沒有在for代碼塊中被修改。示例代碼以下:

for (int i = 0; i < 1; i++) {
    i++;
}
解釋:若是在循環體中修改了控制變量,程序流程就會變得更加難以跟蹤。能夠用while循環替換for循環。

  • MultipleStringLiterals(多重字符串常量)

檢查在單個文件中,相同的字符串常量是否出現了屢次。

解釋:重複代碼會使得維護工做變得更加困難,所以最好用一個常量來替換屢次出現。

  • MultipleVariableDeclaration(多重變量聲明)

檢查每一個變量是否使用一行一條語句進行聲明。

解釋:《SUN編碼規約》的第6.1章節推薦應當使用一行一條語句聲明一個變量。

  • NestedForDepthfor嵌套深度)

限制for循環的嵌套層數(默認值爲1)。

  • NestedIfDepthif嵌套深度)

限制if-else代碼塊的嵌套層數(默認值爲1)。

  • NestedTryDepthtry嵌套深度)

限制try代碼塊的嵌套層數(默認值爲1)。

  • NoClone(沒有clone方法)

檢查是否覆蓋了Object類中的clone()方法。


解釋:clone()方法依賴於一套奇怪且難以遵循的規則,這套規則並非在全部狀況下都起做用。所以,很難正確地覆蓋clone()方法。下面是一些說明爲什麼應當避免使用clone()方法的緣由。

支持clone方法的類應當事先Cloneable接口,可是Cloneable結構並不包含clone方法。所以,它並不會強制覆蓋clone方法。
Cloneable接口會強迫對象的clone方法正確地工做。若是不實現這個接口,那麼對象的clone方法會拋出CloneNotSupportedException。沒有用final關鍵字修飾的類必須返回由調用super.clone()方法所返回的對象。用final關鍵字修飾的類可使用一個構造器建立一個克隆對象,這個對象和非final類的有所不一樣。
若是一個父類沒有正確地實現clone方法,那麼全部的子類調用super.clone()方法時,都會註定失敗。
若是一個類含有可變對象的引用,那麼在這個類的clone方法中調用super.clone()方法以後,必須使用前述可變對象的拷貝來替換這些對象引用。
clone方法不能正確地處理用final關鍵字修飾的可變對象引用,由於final引用不能被從新賦值。
若是一個父類覆蓋了clone方法,那麼全部的子類都必須提供一個正確的clone實現。
在某些狀況下,有兩種clone方法的替代方案可使用,一種是使用一個拷貝構造器,另外一種是使用靜態工廠方法來返回某個對象的拷貝。這兩種方法都更加簡單,而且不會和final關鍵字修飾的字段產生衝突。它們不會強迫調用的客戶端處理CloneNotSupportException。它們都是具備類型的,所以不須要進行任何類型轉換。最後,它們更加靈活,由於它們能夠處理接口類型,而不只僅是實體類。

有時候,不能使用拷貝構造器或靜態工廠做爲clone方法的替代方案。如下示例說明了拷貝構造器或靜態工廠的侷限性。假設Square是Shape的一個子類。
       Shape s1 = new Square();
       System.out.println(s1 instanceof Square); //true
...假設此處的代碼不知道s1是一個Square類型的對象,這是多態的優美之處,可是代碼想要拷貝這個被聲明爲Shape類型的Square對象,Shape是Square的父類...
       Shape s2 = new Shape(s1); //using the copy constructor
       System.out.println(s2 instanceof Square); //false
有效的解決辦法(不用知道全部的子類,而且不用執行大量的類型轉換)應當以下列代碼所示(假設實現了正確的clone方法):
       Shape s2 = s1.clone();
       System.out.println(s2 instanceof Square); //true
你只須要記住,若是須要這種多態克隆的類型,那麼一個正確實現的clone方法可能纔是最好的選擇。

這項檢查和{@link NoFinalizerCheck}幾乎徹底相同。

  • NoFinalizer(沒有finalize方法)

驗證類中是否認義了finalize()方法。

  • OneStatementPerLine//TODO...

每行一條語句。

  • OverloadMethodsDeclarationOrder//TODO...

檢查重載方法被放在一塊兒。

  • PackageDeclaration(包聲明)

確保一個類具備一個包聲明,而且(可選地)包名要與源代碼文件所在的目錄名相匹配。

解釋:位於空包中的類是不可以被導入的。不少開發新手並無注意到這一點。

  • ParameterAssignment(參數賦值)

不容許對參數進行賦值。

解釋:對參數的賦值一般被認爲是缺少編程實踐經驗。強迫開發者將參數聲明爲final一般是很是麻煩的。這項檢查能夠確保參數從不會被賦值,這對於雙方都是好事。

  • RequireThis(須要this

檢查代碼是否使用了「this.」,也就是說,在默認狀況下,引用當前對象的實例變量和方法時,應當顯式地經過「this.varName」或「this.methodName(args)」這種形式進行調用。

  • ReturnCountreturn總數)

限制return語句的數量。默認值爲2。能夠忽略檢查指定的方法(默認忽略equals()方法)。

解釋:過多的返回點可能代表代碼嘗試處理過多的業務,可能會難以理解。

  • SimplifyBooleanExpression(簡化布爾表達式)

檢查是否有過於複雜的布爾表達式。如今可以發現諸如if (b == true)、b || true、!false等類型的代碼。

解釋:複雜的布爾邏輯會使得代碼難以理解和維護。

  • SimplifyBooleanReturn(簡化布爾返回值)

檢查是否有過於複雜的布爾類型return語句。例以下面的代碼:

if (valid())
    return false;
else
    return true;
能夠寫成:
return !valid();
這項檢查是從PMD規則中借鑑而來的。

  • StringLiteralEquality(嚴格的常量等式比較)

檢查字符串對象的比較是否使用了==或!=運算符。

解釋:Java新手程序員常常會使用相似於下面的代碼:

if (x == "something")
其實他們是想表達以下的意思:

if ("something".equals(x))

  • SuperClone(父類clone方法)

檢查一個覆蓋的clone()方法是否調用了super.clone()方法。

參考:Object.clone()。

  • SuperFinalize(父類finalize方法)

檢查一個覆蓋的finalize()方法是否調用了super.finalize()方法。
參考:清理未使用對象。

  • UnnecessaryParentheses(沒必要要的圓括號)

檢查代碼中是否使用了沒必要要的圓括號。

  • VariableDeclarationUsageDistance//TODO...

//TODO...

 

5. Headers(文件頭:2個)

  • Header(文件頭)

檢查源碼文件是否開始於一個指定的文件頭。headerFile屬性能夠指定一個文件,該文件包含了須要的文件頭。還有另外一種方法,文件頭的內容能夠直接在header屬性中設置,而不使用外部文件。

ignoreLines屬性能夠設置行號,指定檢查時忽略頭文件中的哪些行。若是想要支持包含版權日期的文件頭,那麼這個屬性就顯得很是有用。例如,考慮下面的文件頭:
line 1: ////////////////////////////////////////////////////////////////////
line 2: // checkstyle:
line 3: // Checks Java source code for adherence to a set of rules.
line 4: // Copyright (C) 2002  Oliver Burn
line 5: ////////////////////////////////////////////////////////////////////
由於年份信息會隨着時間改變,經過將ignoreLines屬性設置爲4,你就能夠告訴CheckStyle忽略第4行。

  • RegexpHeader(正則表達式文件頭)

檢查Java源碼文件頭部的每行是否匹配指定的正則表達式。

解釋:在某些項目中,檢查固定的頭部是不足夠的,例如,文件頭可能須要一行版權信息,可是其中的年份信息會隨着時間變化。

例如,考慮下面的文件頭:

line  1: ^/{71}$
line  2: ^// checkstyle:$
line  3: ^// Checks Java source code for adherence to a set of rules\.$
line  4: ^// Copyright [Math Processing Error] \d\d\d\d  Oliver Burn$
line  5: ^// Last modification by \$Author.*\$$
line  6: ^/{71}$
line  7:
line  8: ^package
line  9:
line 10: ^import
line 11:
line 12: ^/\*\*
line 13: ^ \*([^/]|$)
line 14: ^ \*/
第1行和第6行說明了如何更緊湊地表示71個'/'符號。第4行表示版權信息中的年份的格式是四位數字。第5行示範瞭如何在文件頭部添加校訂控制關鍵字。第12-14行是Javadoc的模板(第13行很是複雜,它能夠抑制Javadoc註釋中的衝突)。

 

6. Imports(導入:7個)

  • AvoidStarImports(避免通配符導入)

檢查沒有import語句使用*符號。

解釋:從一個包中導入全部的類會致使包之間的緊耦合,當一個新版本的庫引入了命名衝突時,這樣就有可能致使問題發生。

  • AvoidStaticImports(避免靜態導入)

檢查沒有靜態導入語句。

解釋:導入靜態成員可能會致使類成員之間的命名衝突。導入靜態成員可能會致使代碼的可讀性不好,由於讀者可能會搞不清楚成員到底位於哪一個類中。

  • CustomImportOrder//TODO...

//TODO...

  • IllegalImports(非法導入)

檢查是否導入了指定的非法包。默認狀況下,這項檢查會拒絕全部的sun.*包,由於直接使用sun.*包的程序確定不是100%的純Java程序。想要拒絕其餘的包,將illegalPkgs屬性設置爲你指定的非法包列表便可。

  • Import Control(導入控制)

控制容許導入每一個包中的哪些類。可用於確保應用程序的分層規則不會違法,特別是在大型項目中。
導入控制XML文檔所使用的DTD文件位於

http://www.puppycrawl.com/dtds/import_control_1_0.dtd。它包含了上述XML文檔的全部元素和屬性。

 

  • ImportOrder(導入順序檢查)

檢查導入包的順序/分組。確保導入包的分組按照指定的順序排列(例如,java.排在首位,javax.排在第二,以此類推),而且每一個分組內導入的包都是按照字典序排列的。靜態導入必須放在最後,而且也是按照字典序排列的。

  • RedundantImports(多餘導入)

檢查是否存在多餘的導入語句。若是一條導入語句知足如下條件,那麼就是多餘的:

1. 它是另外一條導入語句的重複。也就是,一個類被導入了屢次。

2. 從java.lang包中導入類,例如,導入java.lang.String。

3. 從當前包中導入類。

  • UnusedImports(未使用導入)

檢查未使用的導入語句。CheckStyle使用一種簡單可靠的算法來報告未使用的導入語句。若是一條導入語句知足如下條件,那麼就是未使用的:

1. 沒有在文件中引用。這種算法不支持通配符導入,例如,java.io.*;。大多數IDE檢查帶有通配符的導入語句時,使用的算法很是複雜。

2. 它是另外一條導入語句的重複。也就是,一個類被導入了屢次。

3. 從java.lang包中導入類,例如,導入java.lang.String。

4. 從當前包中導入類。

5. 可選:在Javadoc註釋中引用它。這項檢查默認是關閉的,由於僅僅爲了抽出文檔而引入了一個編譯時依賴是一個很壞的習慣。例如,當Javadoc註釋中包含{@link Date}時,就會認爲import java.util.Date被引用了。想要避免引入編譯時依賴,可把Javadoc註釋寫成{@link java.util.Date}

7. Javadoc Comments(Javadoc註釋12個)

  • AtclauseOrder//TODO...

檢查文檔標籤順序,默認:@author, @version, @param, @return, @throws, @exception, @see, @since, @serial, @serialField, @serialData, @deprecated

  • JavadocMethod(方法註釋)

檢查方法或構造器的Javadoc。默認不會檢查未使用的throws。想要將未聲明的java.lang.RuntimeExceptions也歸入文檔,則須要將allowUndeclaredRTE屬性設置爲true。想要驗證的可見範圍是由scope屬性指定的,默認值爲Scope.PRIVATE。想要驗證其餘的可見範圍,則須要將scope屬性設置爲相應的值。
若是不想顯示因爲參數或類型參數沒有在註釋中使用param標記進行說明而產生的錯誤消息,就須要勾選allowMissingParamTags屬性。若是不想顯示因爲聲明瞭拋出異常但沒有在註釋中使用throws標記進行說明而產生的錯誤消息,就須要勾選allowMissingThrowsTags屬性。若是不想顯示因爲return語句是非void類型但沒有在註釋中使用return標記進行說明而產生的錯誤消息,就須要勾選allowMissingReturnTag屬性。

由@Override註解標記的方法,它的Javadoc不是必需的。可是在Java 5下,沒法爲接口中的方法加上標記(已經在Java 6中修正)。所以,CheckStyle支持使用單個的{@inheritDoc}標記來代替全部其餘的標記。例如,若是下面的方法實現了接口中的某個方法,那麼Javadoc能夠這樣編寫:

/** {@inheritDoc} */
public int checkReturnTag(final int aTagIndex,
                          JavadocTag[] aTags,
                          int aLineNo)

  • JavadocPackage(包註釋)

檢查每一個Java包是否都有Javadoc註釋。默認狀況下,它只容許使用一個package-info.java文件,可是能夠將其配置爲容許使用package.html文件。
若是兩個文件都存在的話,就會報告錯誤,由於Javadoc工具不容許這種狀況發生。

  • JavadocParagraph//TODO...

檢查文檔註釋段落

  • JavadocStyle(風格註釋)

驗證Javadoc註釋,以便於確保它們的格式。能夠檢查如下注釋:接口聲明、類聲明、方法聲明、構造器聲明、變量聲明。

  • JavadocTagContinuationIndentation//TODO...

TODO...

  • JavadocType(類型註釋)

檢查方法或構造器的Javadoc。默認不會檢查author和version標記。想要驗證的可見範圍是由scope屬性指定的,默認值爲Scope.PRIVATE。想要驗證其餘的可見範圍,則須要將scope屬性設置爲相應的值。想要爲author標記或version標記定義格式,將authorFormat屬性或versionFormat屬性設置爲指定的正則表達式便可。
若是不想顯示因爲類型參數沒有在註釋中使用param標記進行說明而產生的錯誤消息,就須要勾選allowMissingParamTags屬性。

  • JavadocVariable(變量註釋)

檢查變量是否具備Javadoc註釋。

  • NonEmptyAtclauseDescription//TODO...

TODO...

  • SingleLineJavadoc//TODO...

TODO...

  • SummaryJavadoc//TODO...

TODO...

  • WriteTag(輸出標記)

將Javadoc做爲信息輸出。能夠做爲樣式表來使用,根據做者名排序報告。想要爲一個標記定義格式,將tagFormat屬性設置爲相應的正則表達式便可。這項檢查會使用兩種不一樣的嚴重級別。當標記缺失時,使用標準的嚴重級別(Severity)。當標記存在時,使用附加的嚴重級別(tagSeverity)做爲報告等級。

 

8. Metrics(度量:6個)

  • BooleanExpressionComplexity(布爾表達式複雜度)

限制一個表達式中的&&、||、&、|、^等邏輯運算符的數量。

解釋:過多的條件會致使代碼難以讀懂、調試和維護。

注意,&和|運算符並不只僅是整數的位運算符,它們仍是布爾運算符&&和||的非快捷版本。

  • ClassDataAbstractionCoupling(類的數據抽象耦合)

這項度量會測量給定類中的其餘類的實例化操做的次數。這種類型的耦合並非因爲繼承或者面向對象範型而產生的。通常而言,任何將其餘抽象數據類型做爲成員的抽象數據類型都具備數據抽象耦合;所以,若是一個類中的某個局部變量是另外一個類的實例(對象),那麼就存在數據抽象耦合(DAC)。DAC越高,系統的數據結構(類)就會越複雜。

  • ClassFanOutComplexity(類的扇出複雜度)

一個給定類所依賴的其餘類的數量。這個數量的平方還能夠用於表示函數式程序(基於文件)中須要維護總量的最小值。

  • CyclomaticComplexity(循環複雜度)

檢查循環複雜度是否超出了指定的限值。該複雜度由構造器、方法、靜態初始化程序、實例初始化程序中的if、while、do、for、?:、catch、switch、case等語句,以及&&和||運算符的數量所測量。它是遍歷代碼的可能路徑的一個最小數量測量,所以也是須要的測試用例的數量。一般1-4是很好的結果,5-7較好,8-10就須要考慮重構代碼了,若是大於11,則須要立刻重構代碼!

  • JavaNCSS(非註釋源碼語句)

經過對非註釋源碼語句(NCSS)進行計數,肯定方法、類、文件的複雜度。這項檢查遵照Chr. Clemens Lee編寫的JavaNCSS-Tool中的規範。
粗略地說,NCSS度量就是不包含註釋的源代碼行數,(近似)等價於分號和左花括號的計數。一個類的NCSS就是它全部方法的NCSS、它的內部類的NCSS、成員變量聲明數量的總和。一個文件的NCSS就是它所包含的全部頂層類的NCSS、imports語句和包聲明語句數量的總和。
解釋:太大的方法和類會難以閱讀,而且維護成本會很高。一個較大的NCSS數值一般意味着對應的方法或類承擔了過多的責任和/或功能,應當分解成多個較小的單元。

  • NPathComplexityNPath複雜度)

NPATH度量會計算遍歷一個函數時,全部可能的執行路徑的數量。它會考慮嵌套的條件語句,以及由多部分組成的布爾表達式(例如,A && B,C || D,等等)。

解釋:在Nejmeh的團隊中,每一個單獨的例程都有一個取值爲200的非正式的NPATH限值;超過這個限值的函數可能會進行進一步的分解,或者至少一探究竟。

 

9. Miscellaneous(雜項:12個)

  • ArrayTypeStyle(數組類型風格)

檢查數組定義的風格。有的開發者使用Java風格:public static void main(String[] args);有的開發者使用C風格:public static void main(String args[])。

  • AvoidEscapedUnicodeCharacters

限制使用 Unicode轉義(例如\ u221e)。容許將轉義用於 不可打印(控制)字符

此外,此檢查能夠配置爲容許使用轉義,若是跟蹤評論存在。經過該選項,若是文字僅包

含它們,則能夠容許使用轉義。

  • CommentsIndentation

 控制註釋和周圍代碼之間的縮進。評論的縮寫與周圍的代碼相同。

  • DescendentToken(後續標記檢查)

檢查在其餘標記之下的受限標記。

警告:這是一項很是強大和靈活的檢查,可是與此同時,它偏向於底層技術,而且很是依賴於具體實現,由於,它的結果依賴於咱們用來構建抽象語法樹的語法。所以,當其餘檢查項目提供了你想要用的功能時,咱們建議你使用這些檢查項目。總之,這項檢查只能在抽象語法樹的層面上工做,它並不瞭解任何語言結構。

  • FileContentsHolder

檢查方法,構造函數和catch塊的參數是否爲final。不檢查接口,抽象和本機方法:final關鍵字對於接口,抽象和本機方法參數沒有意義,由於沒有能夠修改參數的代碼。

理由:在執行方法的算法時更改參數的值可能會使人困惑,應該避免。讓Java編譯器阻止這種編碼風格的一個好辦法就是聲明參數final。

 

  • FinalParametersfinal參數)

檢查方法/構造器的參數是不是final的。這項檢查會忽略接口方法的檢查 —— final關鍵字不會理會接口方法的參數,由於沒有任何代碼可以修改這些參數。
解釋:在方法算法的執行期間改變參數值會使讀者產生混淆,所以應當避免這種狀況的發生。有個很好的方法可使得Java的編譯器預防這種編碼風格,那就是將方法的參數聲明爲final的。

  • Indentation(代碼縮進)

檢查Java代碼的縮進是否正確。

儘管有些格式精美的打印機有時能夠很方便地批量重排原始代碼的格式,可是它們一般不是沒有足夠的可配置性,就是不可以達到預期的排版格式。有時這是我的喜愛的問題,有時這是實際經驗的問題。不管如何,這項檢查應當只確保代碼遵照縮進規則的一個最小集合。

  • NewLineAtEndOfFile(文件末尾的新行)

檢查文件是否以新行結束。

解釋:一般,任何源碼文件和文本文件都應當以一個新行符結束,特別是使用諸如CVS這樣的SCM系統時。當文件沒有以新行結束時,CVS甚至會打印出一個警告。

  • Outer Type File Name(外部類型文件名)

檢查外部類型名稱是否與文件名稱匹配。例如,類Foo必須在文件Foo.java中。

  • TodoCommentTODO註釋)

這項檢查負責TODO註釋的檢查。實際上,這是一種檢查Java註釋的通用正則表達式匹配器。想要檢查其餘格式的Java註釋,那麼設置format屬性便可。

  • TrailingComment(行尾註釋)

這項檢查能夠確保代碼中含有註釋的行中只包含註釋。在使用//註釋的場合下,這意味着//符號以前只能有空格。若是行不是以註釋結束的,那麼就不會檢查這些註釋。例如,下面的代碼是可接受的
Thread.sleep( 10 );
format屬性會處理「} // while」這樣的註釋。

解釋:Steve McConnell編寫的《Code Complete》認爲行尾註釋是一個很差的編程習慣。行尾註釋就是那些和實際代碼位於同一行的註釋。例如:
a = b + c;      // 一條常見的註釋
d = e / f;        // 這一行的另外一條註釋

《Code Complete》爲此給出瞭如下幾條論證:

1. 註釋必須對齊,這樣便不會干擾代碼的可視結構。若是你不將它們整潔地對齊,它們將會使你的代碼看起來就像剛從洗衣機裏出來同樣亂糟糟的。

2. 行尾註釋會很難格式化,須要花費大量的時間來對齊它們。這樣的時間並非花在深刻理解代碼上的,你只能乏味地敲擊空格鍵或製表鍵來從新格式化這些註釋。

3. 行尾註釋很是難以維護。若是某一行包含行尾註釋的代碼增長了,就會使這行的註釋被擠得更遠,而且全部其餘的行尾註釋爲了排版對齊,不得不被放置的一樣遠。難以維護的代碼風格就是不可維護的。

4. 行尾註釋可能會意義不明確。每行的右側一般不能提供足夠的空間來放置註釋,將註釋和代碼放在同一行就意味着註釋可能會比較短。按照這種習慣,你編寫代碼時就會專一於每行儘量的短,而不是每行儘量的清晰。所以,這種註釋常常會意義不明確清晰。
5. 行尾註釋還會帶來一個系統性問題,你會發現很難僅僅在一行中寫出意義明確的註釋。大多數行尾註釋僅僅重複了一下這行的代碼,這種行爲帶來的危害性遠比帶來的幫助要大。

當使用自動化重構技術時,源碼每行的長度會常常變化,這就使得包含大量行尾註釋的代碼變得很是難以維護。

  • Translation(語言轉換)

這是一項FileSetCheck檢查,經過檢查關鍵字的一致性屬性文件,它能夠確保代碼的語言轉換的正確性。可使用兩個描述同一個上下文環境的屬性文件來保證一致性,若是它們包含相同的關鍵字。
考慮下面的屬性文件,它們在同一個目錄中:

#messages.properties
hello=Hello
cancel=Cancel

#messages_de.properties
hell=Hallo
ok=OK


轉換檢查將會發現德語hello關鍵字的拼寫錯誤、默認資源文件(messages.properties)缺乏ok關鍵字、德語資源文件(messages_de.properties)缺乏cancel關鍵字等錯誤:
messages_de.properties: Key 'hello' missing.
messages_de.properties: Key 'cancel' missing.
messages.properties: Key 'hell' missing.
messages.properties: Key 'ok' missing.

  • UncommentedMain(未註釋main方法)

檢查源碼中是否有未註釋的main()方法(調試的殘留物)。

解釋:調試時常常會在代碼中利用main()方法。當調試結束時,開發者常常會忘記刪除這些main()方法,這樣會改變API,而且會增大生成的class/jar文件的尺寸。除了程序真正的入口點以外,源碼中其餘全部的main()方法都應當被刪除或註釋掉。

  • UniqueProperties

檢查重複屬性的屬性文件。

原理:多個屬性鍵一般在合併或從新分支後出現。雖然運行時沒有錯誤,可是因爲具備不一樣的重複屬性值,可能會致使混淆。

  • Upper Ell(大寫「L」

檢查long類型的常量在定義時是否由大寫的「L」開頭。注意,是「L」,不是「l」。這是由《Java Language Specification》的第3.10.1章節所建議的編碼規約。


解釋:小寫字母「l」看起來很是像數字「1」。

 

10. Modifiers(修飾符:2個)

  • ModifierOrder(修飾符順序)

檢查代碼中的標識符的順序是否符合《Java Language Specification》中的第8.1.一、8.3.1章節所建議的順序。正確的順序應當以下:

1. public
2. protected
3. private
4. abstract
5. static
6. final
7. transient
8. volatile
9. synchronized
10. native
11. strictfp

  • RedundantModifier(多餘修飾符)

在如下部分檢查是否有多餘的修飾符:

1. 接口和註解的定義;

2. final類的方法的final修飾符;

3. 被聲明爲static的內部接口聲明。


解釋:《Java Language Specification》強烈不建議在接口定義中使用「public」和「abstract」來聲明方法。

接口中的變量和註解默認就是public、static、final的,所以,這些修飾符也是多餘的。

由於註解是接口的一種形式,因此它們的字段默認也是public、static、final的,正如它們的註解字段默認是public和abstract的。


定義爲final的類是不能被繼承的,所以,final類的方法的final修飾符也是多餘的。

 

11. Naming Conventions(命名規約:15個)

  • AbbreviationAsWordInName//TODO...

//TODO...

  • AbstractClassName(抽象類名稱)

檢查抽象類的名稱是否遵照命名規約。

  • CatchParameterName//TODO...

//TODO...

  • ClassTypeParameterName(類的類型參數名稱)

檢查類的類型參數名稱是否遵照命名規約。

  • ConstantNames(常量名稱)

檢查常量(用static final修飾的字段)的名稱是否遵照命名規約。

  • InterfaceTypeParameterName//TODO...

//TODO...

  • LocalFinalVariableNames(局部final變量名稱)

檢查局部final變量的名稱是否遵照命名規約。

  • LocalVariableNames(局部變量名稱)

檢查局部變量的名稱是否遵照命名規約。

  • MemberNames(成員名稱)

檢查成員變量(非靜態字段)的名稱是否遵照命名規約。

  • MethodName(方法名稱)

檢查方法名稱是否遵照命名規約。

  • MethodTypeParameterName(方法的類型參數名稱)

檢查方法的類型參數名稱是否遵照命名規約。

  • PackageName(包名稱)

檢查包名稱是否遵照命名規約。

  • ParameterName(參數名稱)

檢查參數名稱是否遵照命名規約。

  • StaticVariableName(靜態變量名稱)

檢查靜態變量(用static修飾,但沒用final修飾的字段)的名稱是否遵照命名規約。

  • TypeName(類型名稱)

檢查類的名稱是否遵照命名規約。

 

12. Regexp(正則表達式:5個)

  • Regexp//TODO...

//TODO...

  • RegexpMultiline(正則表達式多行匹配)

檢查多行是否匹配一條給定的正則表達式。能夠處理任何文件類型。

 

解釋:這項檢查能夠做爲原型檢查使用,可以發現常見的編碼壞習慣,例如調用ex.printStacktrace()、System.out.println()、System.exit(),等等。

  • RegexpOnFilename//TODO...

//TODO...

  • RegexpSingleline(正則表達式單行匹配)

檢查單行是否匹配一條給定的正則表達式。能夠處理任何文件類型。

解釋:這項檢查能夠做爲原型檢查使用,可以發現常見的編碼壞習慣,例如調用ex.printStacktrace()、System.out.println()、System.exit(),等等。

  • RegexpSingleLineJava(正則表達式單行Java匹配)

這項檢查是RegexpSingleline的變種,用於檢測Java文件中的單行是否匹配給定的正則表達式。它支持經過Java註釋抑制匹配操做。

 

13. Size Violations(尺寸超標:8個)

  • AnonInnerLength(匿名內部類長度)

檢查匿名內部類的長度。

解釋:若是一個匿名內部類變得很是長,那麼就很難讀懂它,而且難以跟蹤方法的流程。所以,過長的匿名內部類一般應當被重構爲一個具名內部類。能夠參考Bloch編寫的《Effective Java》的第93頁。

  • ExecutableStatementCount(可執行語句數量)

將可執行語句的數量限制爲一個指定的限值。

  • FileLength(文件長度)

檢查源碼文件的長度。

解釋:若是一個源碼文件變得很是長,那麼就會難以理解。所以,過長的類一般應當被重構成若干個較小的獨立的類,每一個類專一於一個特定的任務。

  • LineLength(行長度)

檢查源碼每行的長度。

解釋:將源碼打印出來,或者開發者限制了屏幕顯示源碼的空間(例如,IDE會顯示額外的信息,諸如項目樹、類層次等等),那麼過長的行會顯得難以閱讀。

  • MethodCount(方法總數)

檢查每一個類型中聲明的方法的數量。

它包括了每種可見範圍方法的總數(private、package、protected、public)。

  • MethodLength(方法長度)

檢查方法和構造器的長度。

解釋:若是一個方法變得很是長,那麼就會難以理解。所以,過長的方法一般應當被重構成若干個較小的獨立的方法,每一個方法專一於一個特定的任務。

  • OuterTypeNumber(外層類型數量)

檢查在一個文件的外層(或根層)中聲明的類型的數量。

 

解釋:通常認爲給每一個文件只定義一個外層類型是較好的作法。

  • ParameterNumber(參數數量)

檢查一個方法或構造器的參數的數量。

 

14. Whitespace(空格:16個)

  • EmptyForInitializerPad(空白for初始化語句填充符)

檢查空的for循環初始化語句的填充符,也就是空格是否能夠做爲for循環初始化語句空位置的填充符。若是代碼自動換行,則不會進行檢查,正如如下代碼所示:
for (
      ; i < j; i++, j--)

  • EmptyForIteratorPad(空白for迭代器填充符)

檢查空的for循環迭代器的填充符,也就是空格是否能夠做爲for循環迭代器空位置的填充符。若是代碼自動換行,則不會進行檢查,正如如下代碼所示:

for (Iterator foo = very.long.line.iterator();
      foo.hasNext();
     )

  • EmptyLineSeparator//TODO...

//TODO...

  • FileTabCharacter(文件製表符)

檢查源碼中沒有製表符('\t')。


解釋:

1. 爲了可以更方便地閱讀源碼,開發者不該當在他們的文本編輯器中配置製表符的寬度。

2. 根據Apache Jakarta的編碼標準:在一個分佈式開發環境中,當提交的消息被髮送到一個郵件列表中時,若是你使用了製表符,那麼這些消息會變得幾乎不可能閱讀。

  • GenericWhitespace(範型標記空格)

檢查範型標記<和>的周圍的空格是否遵照標準規約。這項規約是不可配置的。

例如,如下代碼都是合法的:

List x = new ArrayList();
List> y = new ArrayList>();

可是下面的示例代碼是不合法的:

List < Integer > x = new ArrayList < Integer > ();
List < List < Integer > > y = new ArrayList < List < Integer > > ();

  • MethodParamPad(方法參數填充符)

檢查方法定義、構造器定義、方法調用、構造器調用的標識符和參數列表的左圓括號之間的填充符。也就是,若是標識符和左圓括號位於同一行,那麼就檢查標識符以後是否須要緊跟一個空格。若是標識符和左圓括號不在同一行,那麼就報錯,除非將規則配置爲容許使用換行符。想要在標識符以後使用換行符,將allowLineBreaks屬性設置爲true便可。

  • NoLineWrap//TODO...

//TODO...

  • NoWhitespaceAfter(指定標記以後沒有空格)

檢查指定標記以後沒有空格。若要禁用指定標記以後的換行符,將allowLineBreaks屬性設爲false便可。

  • NoWhitespaceBefore(指定標記以前沒有空格)

檢查指定標記以前沒有空格。若要容許指定標記以前的換行符,將allowLineBreaks屬性設爲true便可。

  • OperatorWrap(運算符換行)

檢查代碼自動換行時,運算符所處位置的策略。nl表示運算符必須在新行中,eol表示運算符必須在當前行的行末。

  • ParenPad(圓括號填充符)

檢查圓括號的填充符策略,也就是在左圓括號以後和右圓括號以前是否須要有一個空格。

  • SeparatorWrap//TODO...

//TODO...

  • SingleSpaceSeparator//TODO...

//TODO...

  • TypecastParenPad(類型轉換圓括號填充符)

檢查類型轉換的圓括號的填充符策略。也就是,在左圓括號以後和右圓括號以前是否須要有一個空格。

  • WhitespaceAfter(指定標記以後有空格)

檢查指定標記以後是否緊跟了空格。

  • WhitespaceAround(指定標記周圍有空格)

檢查指定標記的周圍是否有空格。如下形式的空構造器和方法的代碼體(代碼塊):

public MyClass() {}      // 空構造器
public void func() {}    // 空方法
能夠選擇性地從檢查策略中排除,經過設置allowEmptyMethods和allowEmptyConstructors屬性便可。

 

15. Other(其餘:2個)

  • Checker(檢查器)

每一個checkstyle配置的根模塊。不能被刪除。

  • TreeWalker(樹遍歷器)

FileSetCheck TreeWalker會檢查單個的Java源碼文件,而且定義了適用於檢查這種文件的屬性。

 

16. Filters(過濾器:5個)

  • SeverityMatchFilter(嚴重度匹配過濾器)

SeverityMatchFilter過濾器會根據事件的嚴重級別決定是否要接受審計事件。

  • SuppressionCommentFilter(抑制註釋過濾器)

SuppressionCommentFilter過濾器使用配對的註釋來抑制審計事件。


解釋:有時候,違反一項檢查是有正當理由的。當問題出在代碼自己,而不是我的喜愛時,最好在代碼中覆蓋檢查策略。半結構化的註釋能夠和檢查關聯起來。這種作法有時比一個獨立的策略抑制文件更好,由於這個文件必須隨着源碼文件的變化而保持更新。

  • SuppressionFilter(抑制過濾器)

在檢查錯誤時,SuppressionFilter過濾器會依照一個XML格式的策略抑制文件,選擇性地拒絕一些審計事件。若是沒有配置好的策略抑制文件可用,那麼這個過濾器會接受全部的審計事件。

  • SuppressWarningsFilter//TODO...

//TODO...

  • SuppressWithNearbyCommentFilter(抑制附近註釋過濾器)

SuppressWithNearbyCommentFilter過濾器使用獨立的註釋來抑制審計事件。 解釋:和SuppressionCommentFilter相同。然而,SuppressionCommentFilter使用配對的過濾器來打開/關閉註釋匹配,SuppressWithNearbyCommentFilter則使用單個註釋過濾器。這樣可使用更少的行數來標記一塊區域,在某些環境中會顯得風格很優美。 用法:這個過濾器須要和FileContentsHolder協同使用,由於檢查器能夠在.java文件中不公開地使用抑制註釋。包含這個過濾器的配置文件必須將FileContentsHolder配置爲TreeWalker的一個子模塊。

相關文章
相關標籤/搜索