一、前言
在項目開發的過程中,很多時候,無法統一大家的編碼規範,你有你的風格,我有我的風格,雖然每個公司都有自己的規範,但是有時候,作爲開發人員的我們,寫者寫着,就按自己的來了,反正有沒有人來檢查,或者是人爲的檢查感覺費時間,這時候,就可以通過一些代碼插件工具來提高我們的效率,目前常見的有:CheckStyle、阿里巴巴的p3c插件等。
CheckStyle簡介
CheckStyle是一個幫助程序員來遵守一直的編碼規範的工具。默認,它支持google 和sun 的java style guide。而且它是高度可配置的,允許自定義編碼規範,並可以對各種IDE(eclipse、Intellij)和構建工具(maven,gradle)的支持。
P3C簡介
該插件主要是對今年發佈的《阿里巴巴 Java 開發規約》的一個延伸,它以一個 IDE 的插件存在,可以自動對手冊中的 Java 不規範的問題進行提示。現在主要支持(IDEA、Eclipse),Android Studio 是基於 IDEA 的,所以也是支持 Android 開發人員的。該插件在掃描代碼後,會將不符合規約的代碼按照 Blocker/Critical/Major 三個等級顯示在下方,甚至在 IDEA 上,還可以基於 Inspection 機制提供了實時檢測的功能,編寫代碼的同時也能快速發現不規範的代碼。而對於歷史代碼,部分規則實現了批量一鍵修復的功能,爲首次在成熟項目上,使用插件,做了非常友善的支持。
注意:
這裏我們主要講工具的使用,並沒有講代碼編寫的一些規範,目前講的很詳細的有《阿里巴巴Java開發手冊》可以參考他的語法。
二、安裝
這裏分別以IDEA和Eclipse來演示安裝:
2.1、Eclipse安裝CheckStyle、P3C
2.1.1、安裝CheckStyle
Eclipse中,選擇Help->Eclipse Marketplace
點擊Install
點擊Confirm
安裝後重啓即可
2.1.2、安裝P3C
輸入Update Site地址:https://p3c.alibaba.com/plugin/eclipse/update 回車,然後勾選Ali-CodeAnalysis,再一直點Next Next...按提示走下去就好。
然後就是提示重啓了,安裝完畢。
2.2、IDEA安裝CheckStyle、P3C
IDEA安裝就更簡單了,步驟如下:
settings---->plugins
輸入你要安裝的插件,然後點擊安裝就行了,安裝好之後,也得重啓下。
三、使用
(一)、CheckStyle使用
3.1、Checkstyle全局配置
Window -->Preferences,選擇checkstyle菜單,增加項目組統一的規則文件,並設置爲默認規則。如下圖:
Checkstyle默認提供的配置文件有兩個:
一是Sun Checks,對應的配置文件是google_checks.xml文件,含義是Checkstyle configuration that checks the sun coding conventions,一般Sun Checks的檢查項限定得較爲嚴格,我們實際項目中並不要求那麼完美的編程規範,那麼可以自己定義檢查的配置文件,最後將Checkstyle的配置文件設定爲我們自定義的文件即可。
另一個是Google Checks,對應的配置文件是google_checks.xml,一般Checkstyle默認的設置就是sun_checks.xml配置文件。
點擊“New”按鈕後,彈出“Check Configuration Properties”窗口,如下圖所示:
在上圖中選擇“Type”爲“External Configuration File”(外部配置文件),在“Location”行點擊“Browse”按鈕瀏覽選擇checkstyle的配置文件,例如eclipse_checkstyle.xml文件(僅供參考,可自行定義),並輸入“Name”行的值,例如“eclipse_checkstyle”,點擊“OK”按鈕完成導入操作。回到Checkstyle主頁面選擇剛纔添加的文件,點擊“Set As Default”將其設置爲默認checkstyle檢查文件。
注意:
文件的格式必須要UTF-8,否則會提示錯誤:unable to parse configuration stream
3.2、Checkstyle項目配置
項目 --> 右鍵Properties
配置好之後,點擊Apply and Close,此時CheckStyle已經開始運行了。然後你就會發現發現項目上有很多紅叉叉,說明是代碼不符合規範造成的。
3.3、其他操作
在項目右鍵菜單中,checkstyle還有一些快捷操作,如下圖所示:
還可以可視化進行查看: windows---->show view
3.4、Checkstyle的配置
Checkstyle配置是通過指定modules來應用到java文件的。modules是樹狀結構,以一個名爲Checker的module作爲root節點,一般的checker都會包括TreeWalker子module。我們可以參照checkstyle中的sun_checks.xml,這是根據sun的java語言規範寫的配置。
在xml配置文件中通過module的name屬性來區分module,module的Properties可以控制如何去執行這個module,每個property都有一個默認值,所有的check都有一個severity屬性,用它來指定check的level。TreeWalker爲每個java文件創建一個語法樹,在節點之間調用submodules的Checks。
下面來看看standard checks中的一些具體用法。
Javadoc Comments
l JavadocPackage
檢查每個java package中是否有java註釋文件,默認是允許一個package-info.java,也可以通過allowLegacy屬性配置允許package.html。
l JavadocType
檢查類和接口的javadoc。默認不檢查author 和version tags。
l JavadocMethod
檢查方法和構造函數的javadoc。默認不檢查未使用的異常拋出。
l JavadocVariable
檢查變量的javadoc。
l JavadocStyle
檢查javadoc的格式。比如:javadoc的第一行是否以句號結束,javadoc除了tags外是否有description,檢查javadoc中的html格式。
l WriteTag
輸出javadoc中的tag。
Naming Conventions
l AbstractClassName
檢查抽象類名。
l ClassTypeParameterName
檢查類的Parameter名。
l ConstantName
檢查常量名。
l LocalFinalVariableName
檢查局部的final類型變量名,包括catch的參數。
l LocalVarableName
檢查局部的非final類型的變量名,包括catch的參數。
l MemberName
檢查非靜態變量。
l MethodName
檢查方法名。
l MethodTypeParameterName
檢查方法的參數名。
l PackageName
檢查包名。
l ParameterName
檢查參數名。
l StaticVariableName
檢查靜態的,非final類型的變量名。
l TypeName
檢查類名和接口名。
Imports
l AvoidStarImport
檢查是否有使用*進行import。
l AvoidStaticImport
檢查是否有靜態import。比如是否導入了java.lang包中的內容。
l IllegalImport
檢查是否import了違法的包。默認拒絕import所有sun.*包。
l RedundanImport
檢查是否有重複的import。
l UnusedImports
檢查是否有未使用的import。
l ImportOrder
檢查import的分組和順序。
l ImportControl
控制可import的包。在一個較大的project可限制使用過多的第三方包,通過一個依照http://www.puppycrawl.com/dtds/import_control_1_0.dtd的xml文件來指定。
Size Violations
l ExecutableStatementCount
限制可執行代碼片段的長度。默認爲30。
l FileLength
檢查java文件的長度。默認爲2000。
l LineLength
檢查代碼行的長度。默認爲80。
l MethodLength
檢查方法和構造函數的長度。默認爲150。
l AnonInnerLength
檢查匿名內部類的長度。默認爲20。
l ParameterNumber
檢查方法和構造函數的參數個數。默認爲7。
Whitespace
l GenericWhitespace
檢查<和>周圍的空白。
l EmptyForInitializerPad
檢查空的初始化位置的空白。比如for循環中的初始化。
l EmptyForIteratorPad
檢查空的迭代位置的空白。
l MethodParamPad
檢查方法簽名之前的空白。
l NoWhitespaceAfter
檢查分隔符後的空白。
l NoWhitespaceBefore
檢查分隔符前的空白。
l OperatorWrap
檢查操作符的空白規則。
l ParenPad
檢查圓括號的空白規則。
l TypecaseParenPad
檢查強制轉型的圓括號的空白規則。
l TabCharacter
檢查是否有Tab字符(’"t’)。
l WhitespaceAfter
檢查分隔符是否在空白之後。
l WhitespaceAround
檢查分隔符周圍是否有空白。
ModifierOrder
l ModifierOrder
檢查修飾符的順序是否遵照java語言規範。
l RedundantModifier
檢查接口和annotation中是否有重複的修飾符。
Block Checks
l EmptyBlock
檢查空的代碼塊。
l LeftCurly
檢查’{’和左邊的代碼塊是否在同一行。
l NeedBraces
檢查是否需要大括號。主要是在if,else時的情況。
l RightCurly
檢查’}’。
l AvoidNestedBlocks
檢查不需要的嵌套’{}’。
Coding
l ArrayTrailingComma
檢查數組初始化是否以逗號結束。
l AvoidInlineConditionals
檢查inline的條件操作。
l CovariantEquals
檢查類是否覆蓋了equals(java.lang.Object)。
l DoubleCheckedLocking
檢查DCL的問題。
l EmptyStatement
檢查空的代碼段。
l EqualsAvoidNull
檢查一個可能爲null的字符串是否在equals()比較的左邊。
l EqualsHashCode
檢查類是否覆蓋了equals()和hashCode()。
l FinalLocalVariable
檢查未改變過的局部變量是否聲明爲final。
l HiddenField
檢查局部變量或參數是否隱藏了類中的變量。
l IllegalInstantiation
檢查是否使用工廠方法實例化。
l IllegalToken
檢查非法的分隔符。
l IllegalTokenText
檢查非法的分隔符的下個字符。
l InnerAssignment
檢查子表達式中是否有賦值操作。
l MagicNumber
檢查是否有“magic numbers”。
l MissingSwitchDefault
檢查switch語句是否有default的clause。
l ModifiedControlVariable
檢查循環控制的變量是否在代碼塊中被修改。
l RedundantThrows
檢查是否有被重複拋出的異常。
l SimplifyBooleanExpression
檢查是否有過度複雜的布爾表達式。
l SimplifyBooleanReturn
檢查是否有過於複雜的布爾返回代碼段。
l StringLiteralEquality
檢查字符串是否有用= =或!=進行操作。
l NestedIfDepth
檢查嵌套的層次深度。
l NestedTryDepth
檢查try的層次深度。
l NoClone
檢查是否覆蓋了clone()。
l NoFinalizer
檢查是否有定義finalize()。
l SuperClone
檢查覆蓋的clone()是否有調用super.clone()。
l SuperFinalize
檢查覆蓋的finalize()是否有調用super.finalize()。
l IllegalCatch
檢查是否catch了不能接受的錯誤。
l IllegalThrows
檢查是否拋出了未聲明的異常。
l PackageDeclaration
檢查類中是否有聲明package。
l JUnitTestCase
確保setUp(), tearDown()方法簽名的正確性。
l ReturnCount
限制return代碼段的數量。
l IllegalType
檢查未使用過的類。
l DeclarationOrder
檢查類和接口中的聲明順序。
l ParameterAssignment
檢查不允許的參數賦值。
l ExplicitInitialization
檢查類和對象成員是否初始化爲默認值。
l DefaultComesLast
檢查default的clause是否在switch代碼段的最後。
l MissingCtor
檢查類依賴。
l FallThrough
檢查switch代碼的case中是否缺少break,return,throw和continue。
l MultipleStringLiterals
檢查一個文件中是否有多次出現的字符串。
l MultipleVariableDeclarations
檢查代碼段和代碼行中是否有多次變量聲明。
l RequireThis
檢查代碼中是否有“this.”。
l UnnecessaryParentheses
檢查是否有使用不需要的圓括號。
Class Design
l VisibilityModifier
檢查類成員的可見度。
l FinalClass
檢查只有private構造函數的類是否聲明爲final。
l InterfaceIsType
檢查接口是否僅定義類型。
l HideUtilityClassConstructor
檢查工具類是否有putblic的構造器。
l DesignForExension
檢查類是否爲擴展設計。
l MutableException
確保異常是不可變的。
l ThrowsCount
限制拋出異常的數量。
Duplicate Code
l StrictDuplicateCode
嚴格檢查重複代碼。
Miscellaneous
l GenericIllegalRegexp
正則表達式的模式檢查。
l NewlineAtEndOfFile
檢查文件是否以一個空行結束。
l TodoComment
檢查TODO:註釋。
l Translation
檢查property文件中是否有相同的key。
l UncommentedMain
檢查是否有未註釋的main方法。
l UpperEll
檢查long型約束是否有大寫的“L”。
l ArrayTypeStyle
檢查數組類型定義的樣式。
l FinalParameters
檢查方法名、構造函數、catch塊的參數是否是final的。
l Indentation
檢查代碼中正確的縮進。
l TrailingComment
確保是否要代碼行註釋。
l RequiredRegexp
確保一個指定的正則表達式的規則已經存在代碼中。
詳細請參考: http://blog.csdn.net/weidawei0609/article/details/7302911
3.5、自定義CheckStyle規範
Checkstyle沒有圖形化的定製器,所以需要手工修改配置文件。比如,我們的代碼需要符合下列規則:
* 長度方面:文件長度不超過1500行,每行不超過120個字,方法不超過60行.
* 命名方面:類名不能小寫開頭,方法名不能大寫開頭,常量不能有小寫字母。
* 編碼方面:不能用魔法數(Magic Number),if最多嵌套3層。
那麼,我們的檢查配置文件(如命名成 eclipse_checkstyle.xml )應該是這樣的:
下面是對具體的check的描述。這些check可以被分爲了15類,如下所示:
===== CHECK STYLE ========
----- Annotations -------- JDK5中的Annotation相關(未展開)
----- Block Checks ------- 代碼塊相關
----- Class Design ------- 類設計相關
----- Coding ------------- 編碼相關
----- Duplicate Code ----- 冗餘代碼
----- Headers ------------ 源文件的頭
----- Imports ------------ 引入包相關
----- Javadoc Comments --- JavaDoc相關
----- Metrics ------------ 複雜度分析
----- Miscellaneous ------ 其它
----- Modifiers ---------- 修飾符相關
----- Naming Conventions - 命名規範
----- Regexp ------------- 正則表達式相關
----- Size Violations ---- 文件大小等相關
----- Whitespace --------- 空格處理相關
==========================
詳細的可以參考這:http://blog.csdn.net/yang1982_0907/article/details/18086693
一個示例:
基於華爲java編程規範的checkstyle.xml以及格式化模版,註釋模版
3.6、常見的一些錯誤提示:
1 提示:Type is missing a javadoc commentClass
說明:缺少類型說明
解決方法:增加javadoc說明
2 提示:“{” should be on the previous line
說明:“{”應該位於前一行。
解決方法:把“{”放到上一行去
3 提示:Methos is missing a javadoc comment
說明:方法前面缺少javadoc註釋。
解決方法:添加javadoc註釋
4 提示: Expected @throws tag for“Exception”
說明:在註釋中希望有@throws的說明
解決方法:在方法前得註釋中添加這樣一行:* @throws Exception if has error(異常說明)
5 提示:“.” Is preceeded with whitespace
說明: “.” 前面不能有空格。
解決方法:把“.”前面的空格去掉
6 提示:“.” Is followed by whitespace
說明:“.” 後面不能有空格。
解決方法:把“.”後面的空格去掉
7 提示:“=” is not preceeded with whitespace
說明:“=” 前面缺少空格。
解決方法:在“=”前面加個空格
8 提示:“=” is not followed with whitespace
說明:“=” 後面缺少空格。
解決方法:在“=”後面加個空格
9 提示:“}” should be on the same line
說明:“}” 應該與下條語句位於同一行。
解決方法:把“}”放到下一行的前面
10 提示:Unused @param tag for “unused”
說明:沒有參數“unused”,不需註釋
解決方法:“* @param unusedparameter additional(參數名稱)” 把這行unused參數的註釋去掉“
11 提示: Variable “CA” missingjavadoc
說明:變量“CA”缺少javadoc註釋
解決方法:在“CA“變量前添加javadoc註釋:/** CA. */(注意:一定記得加上CA後面的“.”)
12 提示: Line longer than 80characters
說明:行長度超過80 。
解決方法:把它分成多行寫。必要時候,可以ctrl+shift+f
13 提示:Line contains a tab character
說明:行含有”tab” 字符。
14 提示:Redundant “Public” modifier
說明:冗餘的“public” modifier 。
解決方法:冗餘的“public”
15 提示:Final modifier out of order with the JSL suggestion
說明:Final modifier的順序錯誤
16 提示: Avoid using the “.*” formof import
說明:Import格式避免使用“.*”
17 提示:Redundant import from the same package
說明:從同一個包中Import內容
18 提示: Unusedimport-java.util.list
說明:Import導入進來的java.util.list沒有被使用。
解決方法:去掉導入的多餘的類
19 提示:Duplicate import to line 13
說明:重複Import同一個內容
解決方法:去掉導入的多餘的類
20 提示: Import from illegalpackage
說明:從非法包中 Import內容
21 提示:“while” construct must use “{}”
說明:“while” 語句缺少“{}”
22 提示: Variable “sTest1” must beprivate and have accessor method
說明:變量“sTest1”應該是private的,並且有調用它的方法
23 提示: Variable “ABC” must matchpattern “^[a-z][a-zA-Z0-9]*$”
說明:變量“ABC”不符合命名規則“^[a-z][a-zA-Z0-9]*$”
解決方法:把這個命名改成符合規則的命名 “aBC”
24 提示:“(” is followed by whitespace “)”is proceeded by whitespace
說明:“(” 後面不能有空格 “)” 前面不能有空格
解決方法:把前面或者後面的空格去掉
25 提示:First sentence should end with a period.
解決方法:你的註釋的第一行文字結束應該加上一個"."。
26提示: Redundant throws:'NameNotFoundException' is subclass of 'NamingException'.
說明:'NameNotFoundException '是'NamingException'的子類重複拋出異常。
解決方法:如果拋出兩個異常,一個異常類是另一個的子類,那麼只需要寫父類
去掉NameNotFoundException異常,對應的javadoc註釋異常註釋說明也需要去掉
27 提示: Parameter docType should be final.
說明: 參數docType應該爲final類型
解決方法:在參數docType前面加個final
28 提示: Line has trailing spaces.
說明:多餘的空行
解決方法:去掉這行空行
29 提示: Must have at least onestatement.
說明: 至少有一個聲明
解決方法:try{}catch(){}中的異常捕捉裏面不能爲空,在異常裏面加一句話。如打印等
30 提示:'>' is not followed by whitespace.並且又有 '('is preceded with whitespace.
說明:定義集合和枚舉的時候的時候,最後一個“>”後面要有空格,“(”前面不容許有空格。
解決方法:去掉泛型(通常是泛型的地方容易出這個問題)
31 提示:Got an exception - java.lang.RuntimeException: Unable to get classinformation for @throws tag 'SystemException'.
說明:不合理的throws。
解決方法:要確保某些類型,如某些類、接口不被throws。把聲明的異常去掉。在實現類中拋出異常
網上參考解決方法:1、這是CheckStyle報的錯。通常需要Refreh, clean/build這個Project.如果不行,可以嘗試clean all projects, restart Eclipse.
2、因爲編譯好的類沒有在checkstyle的classpath中.所以, 只要將編譯好的class配置到在<checkstyle/>的classpath中就沒有這個問題了.另外, 還發現checkstyle的line length好像也有點問題, 明明沒有超過120個字符, 卻還是報錯.無奈, 我把Eclipse中java> code style > formatter中的Maximumline with改成了100, 然後format一下, 基本就沒有問題了
32 提示: File does not end with anewline.
解決方法:刪掉報錯的類,新建一個同名的類,把代碼全部複製過去
33 提示:Utility classes should not have a public or default constructor.
說明: 接口中的內部類中不應該有公共的或者默認的構造方法
解決方法:在內部類中,定義一個私有的構造方法,然後內部類聲明爲final類型。如果前面有static,那麼final還必須放在static之後
34 提示:Variable 'functionCode' must be private and have accessor methods
說明:.變量要改成private然後提供訪問的方法
解決方法:給這些變量的修飾符改成private,然後提供set,get方法,並加上對應的方法javadoc註釋、參數註釋。並在返回值和參數類型前添加final。並把調用了這個變量的地方改成通過方法訪問
35 提示: 'X' hides a field.
說明:全局private int X;和局部publicFoo(int X)的X變量名字重複。
解決方法:把方法裏面的參數名稱改變下就可以了public Foo(int newBar)
36 提示: Got an exception -Unexpected character 0xfffd in identifier
說明:這是因爲CheckStyle不能識別制定的編碼格式。
網上參考解決方法:
1、Eclipse中可以配置,在Other-->checker中可以指定
2、可以修改checkstyle配置文件:
<modulename="Checker">
<propertyname="severity" value="warning"/>
<property name="charset"value="UTF-8"/>
<modulename="TreeWalker">
如果是UTF-8的話,就添加加粗斜體的那條語句,就可以了。
37 提示: Got an exception -java.lang.RuntimeException: Unable to get class information for @throws tag*whatever*.
網上參考解決方法:選中CheckSytle的JavaDoc--> Method JavaDoc --> logLoadErrors。如果是CheckStyle自己加載時出錯的,打個Log就可以了,不要整出Errors嚇人。(這個問題沒遇到過,所以沒做過嘗試)
還有一處也可能包出同樣的錯誤。Coding Problems -->Redundant Throws --> logLoadErrors選中即可
38 提示: Expected @param tag for 'dataManager'.
說明:缺少dataManager參數的註釋
解決方法:在註釋中添加@param dataManager DataManager
(二)、P3C使用
項目右鍵、然後使用阿里巴巴掃描,結果如下
將不符合規約的代碼按Blocker/Critical/Major三個等級顯示在下方,規範裏的詳細信息可以在: windows---->Preferences---->Alibaba Code Analysis中進行查看: